Skip to content
Snippets Groups Projects
Commit 6c5600f2 authored by Quentin Leblanc's avatar Quentin Leblanc
Browse files

serie 8

parent ef697c04
Branches
No related tags found
No related merge requests found
TP3/build.sbt 100644 → 100755
File mode changed from 100644 to 100755
File mode changed from 100644 to 100755
File mode changed from 100644 to 100755
File mode changed from 100644 to 100755
File mode changed from 100644 to 100755
File mode changed from 100644 to 100755
package ch.hepia.tpscala.monoid
import ch.hepia.tpscala.monoid
trait Monoid[A] {
def op( a1: A, a2: A ): A
def zero: A
}
object Monoid {
def apply[A]( z: A )( f: (A,A)=>A ) = new Monoid[A] {
def op( a1: A, a2: A ): A = f(a1,a2)
def zero: A = z
}
object Laws {
def checkAssociativity[A](
mon: Monoid[A], a1: A, a2: A, a3: A
) = {
import mon.op
op(a1,op(a2,a3)) == op(op(a1,a2),a3)
}
def checkNeutral[A](
mon: Monoid[A], a: A
) = {
import mon._
op(zero,a) == a && op(a,zero) == a
}
}
}
object Monoids {
val intSum = Monoid(0)( _ + _ )
val intProd = Monoid(1)( _ * _ )
val doubleSum = Monoid( 0.0 )( _ + _ )
val doubleMax = Monoid( Double.MinValue )( _ max _ )
val doubleMin = Monoid( Double.MaxValue )( _ min _ )
def listFlat[A] = Monoid[List[A]]( Nil )( _ ++ _ )
def setUnion[A] = Monoid( Set.empty[A] )( _ ++ _ )
def pipeline[A] = Monoid[A=>A]( identity )( _ andThen _ )
def optionM[A]( op: (A,A)=>A ) =
Monoid[Option[A]]( None ){ (lhs,rhs) =>
(lhs,rhs) match {
case (None,_) => rhs
case (_,None) => lhs
case (Some(a),Some(b)) => Some( op(a,b) )
}
}
val optIntProd = optionM( intProd.op )
val optDoubleMax = optionM( doubleMax.op )
def tuple2M[A,B]( MA: Monoid[A], MB: Monoid[B] ) =
Monoid[(A,B)]( (MA.zero,MB.zero) ){ (ab1,ab2) =>
( MA.op( ab1._1, ab2._1 ), MB.op( ab1._2, ab2._2 ) )
}
def mapM[K,V]( M: Monoid[V] ) = {
def merge( lhs: Map[K,V], rhs: Map[K,V] ): Map[K,V] = {
val ks = lhs.keySet ++ rhs.keySet
ks.map{ k =>
val v = M.op(
lhs.getOrElse(k,M.zero),
rhs.getOrElse(k,M.zero) )
k -> v
}.toMap
}
Monoid[Map[K,V]]( Map() )( merge )
}
}
object Examples {
import Monoids._
def mapReduce[A,B]( as: List[A] )(f: A=>B, M: Monoid[B]): B = {
def rec( rem: List[A], acc: B ): B = rem match {
case Nil => acc
case h :: t => rec( t, M.op(acc, f(h) ) )
}
rec( as, M.zero )
}
def reduce[A]( as: List[A] )( M: Monoid[A] ): A =
mapReduce( as )( identity, M )
//Donné à titre d'exemple
def averageM[A]( MA: Monoid[A] ): Monoid[(A,Int)] =
tuple2M( MA, intSum )
val avgDouble = averageM( doubleSum )
def average( as: List[Double] ): Option[Double] =
if( as.isEmpty ) None
else {
val (sum,n) =
mapReduce( as )( a => (a,1), avgDouble )
Some( sum/n )
}
//Série 3: and
def and( xs: List[Boolean] ): Boolean = reduce(xs)(Monoid[Boolean](true)(_ && _))
//Retourne le min et le max d'une liste de doubles en un seul parcours
def minMax( as: List[Double] ): (Double,Double) = mapReduce[Double, (Double, Double)](as)((a:Double) => (a, a), tuple2M(doubleMin, doubleMax))
//Série 3: Even
def even[A]( as: List[A] ): Boolean = mapReduce[A, Int](as)(_ => 1, intSum)%2 == 0
//Compte le nombre d'occurence de chaque objet de la liste
def count[A]( as: List[A] ): Map[A,Int] = mapReduce[A, Map[A, Int]](as)((x: A) => Map[A, Int](x -> 1), mapM[A, Int](Monoid[Int](0)(_ + _)))
//Compte le nombre d'occurence de chaque pair d'objet
def count2[A,B]( as: List[(A,B)] ): Map[A,Map[B,Int]] = mapReduce[(A,B), Map[A,Map[B, Int]]](as)( (x:(A,B)) => Map(x._1 -> Map(x._2 -> 1)),mapM[A,Map[B, Int]](mapM[B, Int](Monoid[Int](0)(_ + _))))
//Série 4: forall
def forall[A]( ps: List[(A)=>Boolean] ): (A)=>Boolean = (a:A) => { mapReduce(ps)((p:A=>Boolean) => p(a), Monoid[Boolean](true)(_ && _)) }
}
File mode changed from 100644 to 100755
File mode changed from 100644 to 100755
File mode changed from 100644 to 100755
File mode changed from 100644 to 100755
package ch.hepia.tpscala.monoid
import org.scalatest.funsuite.AnyFunSuite
import Examples._
class Monoid8Suite extends AnyFunSuite {
test( "minMax" ) {
assert( minMax( List(1,2,3,4,5,6) ) == (1,6) )
assert( minMax( List(1) ) == (1,1) )
assert( minMax( List(2,2,2,2,2,2,2,2) ) == (2,2) )
assert( minMax( List(100,-100) ) == (-100, 100) )
}
test( "and" ) {
assert( and(Nil) && and(List(true)) == true )
assert( and(List( true, true, true )) == true )
assert( and(List( true, true, false )) == false )
}
test( "even" ) {
assert( even( Nil ) == true )
assert( even( List(0) ) == false )
assert( even( List(0,0) ) == true )
assert( even( List(0,0,0) ) == false )
assert( even( List(0,0,0,0) ) == true )
assert( even( List(0,0,0,0,0) ) == false )
}
test( "count" ) {
assert( count( List("y", "n", "y", "y", "n", "y") ) == Map( "y"->4, "n"->2 ) )
assert( count(Nil) == Map() )
assert( count( List(1,2,3,4,5) ) == Map( 1->1, 2->1, 3->1, 4->1, 5->1 ) )
}
test( "count2" ) {
assert(
count2( List( ("a","y"), ("a", "y"), ("b","y"), ("b","n"), ("c","y") ) ) ==
Map(
"a" -> Map("y"->2),
"b" -> Map ("y"->1, "n"->1),
"c" -> Map("y"->1 )
)
)
}
test( "forall" ) {
val big = (_:Int) >= 100
val even = (_:Int) % 2 == 0
val mul3 = (_:Int ) % 3 == 0
val ps = forall( List( big, even, mul3 ) )
assert( ps( 402 ) )
assert( ! ps( 200 ) )
assert( forall( Nil )( 402 ) )
assert( forall( Nil )( 200 ) )
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment