Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
  • master
1 result

Target

Select target project
  • joel.cavat/scala2020
  • alexandr.favre1/scala2020
  • alexandr.arondel/scala2020
  • joel.vonderwe/scala2020
4 results
Select Git revision
  • master
1 result
Show changes
Commits on Source (7)
Showing
with 585 additions and 0 deletions
../.idea/
target/
.idea/
No preview for this file type
No preview for this file type
name := "TP2"
version := "0.1"
scalaVersion := "2.13.1"
scalaSource in Compile := baseDirectory.value / "src"
javaSource in Compile := baseDirectory.value / "java" / "src"
scalaSource in Test := baseDirectory.value / "test"
sbt.version = 1.3.7
\ No newline at end of file
package ch.hepia.tp2
import java.util._
class Stack[A] {
private val content: List[A] = new ArrayList[A]
//Return true if Stack is Empty
def isEmpty: Boolean = content.isEmpty
//return size of stack
def size: Int = content.size
//stack an element on the stack
def push(a: A): Unit = content.add(0, a)
//Unstack an element and return it
def pop: A = {
if(this.size == 0 ) {
throw new NoSuchElementException
}else{
content.remove(0)
}
}
//Swap the 2 first elements of the stack, do nothing if less than 1 element
def swap: Unit = {
if(this.size > 1) {
this.push(content.remove(1))
}
}
override def toString: String = {
val sb: StringBuilder = new StringBuilder
sb.append("[")
this.content.forEach((e) => sb.append(e).append(", "))
sb.append("]")
sb.toString
}
}
name := "TP3"
version := "0.1"
scalaVersion := "2.13.1"
libraryDependencies += "org.scalactic" %% "scalactic" % "3.1.0"
libraryDependencies += "org.scalatest" %% "scalatest" % "3.1.0" % "test"
\ No newline at end of file
sbt.version = 1.3.7
\ No newline at end of file
package ch.hepia.scala
/*
* Implémenter les fonctions suivantes en suivant les commentaires.
* Respectez également les consignes suivantes:
* - Toutes les fonctions doivent être pures
* - Tout doit être immutable (val au lieu de var)
* - Utiliser la recursion terminale si possible
* - Utiliser le pattern matching si possible
*/
object Serie3 {
/*
* Donne la longueur d'une liste. Votre implémentation ne peut
* utiliser aucune fonction de List excepté isEmpty()
*/
def len[A]( as: List[A] ): Int = {
@scala.annotation.tailrec
def size(rem: List[A], s: Int): Int = {
rem match {
case Nil => s
case _ :: bs => size(bs, s+1)
}
}
size(as, 0)
}
/*
* Inverse l'ordre des elements d'une liste. Votre implémentation ne peut
* utiliser aucune fonction de List excepté: -
* - isEmpty
* - ::
* - head
* - tail
*/
def rev[A]( as: List[A] ): List[A] = {
@scala.annotation.tailrec
def takeLast(rem: List[A], bs: List[A]): List[A] = {
rem match {
case Nil => bs
case a :: tail => takeLast(tail, a::bs)
}
}
takeLast(as, Nil)
}
/*
* Somme les elements d'une liste. Votre implémentation ne peut
* utiliser aucune fonction de List excepté: -
* - isEmpty
* - head
* - tail
*/
def sum( xs: List[Int] ): Int = {
@scala.annotation.tailrec
def acc(rem: List[Int], s: Int): Int ={
rem match{
case Nil => s
case a :: bs => acc(bs, s+a)
}
}
acc(xs, 0)
}
/*
* Retourne vrai si et seulement si la liste xs ne
* comprend que des valeures vraies. Votre implémentation
* ne peutcutiliser aucune fonction de List excepté:
* - isEmpty
* - head
* - tail
*/
@scala.annotation.tailrec
final def and(xs: List[Boolean] ): Boolean = {
xs match {
case Nil => true
case true :: bs => and(bs)
case _ => false
}
}
/*
* Applatit une liste. Votre implémentation
* ne peut utiliser aucune fonction de List excepté:
* - isEmpty
* - head
* - tail
* - ++
*
*/
def flat[A]( las: List[List[A]] ): List[A] = {
@scala.annotation.tailrec
def through(as: List[List[A]], dst: List[A]): List[A] = {
as match {
case Nil => dst
case Nil::bs => through(bs, dst)
case (head::tail):: bs => through(tail::bs, head::dst)
}
}
rev(through(las, Nil))
}
/*
* Retourne vrai si la Liste a une nombre pair d'éléments. Votre
* implémentation ne peut utiliser aucune fonction de List ! Vous
* devez utiliser le pattern matching.
*/
final def even[A]( as: List[A] ): Boolean = as match{
case Nil => true
case _ :: Nil => false
case _ :: _ :: rest => even(rest)
}
}
object Serie3Main extends App {
import Serie3._
val is = List( 1, 2, 3, 4, 5 )
val bs1 = List( true, true, false, true )
val bs2 = List( true, true, true )
val las1 = List.empty[List[Int]]
val las2 = List( List(1,2), List(3), List(4,5) )
println("1st")
require( rev(is) == List( 5, 4, 3, 2, 1 ) )
println("2nd ")
require( len(is) == 5 )
require( len( las1 ) == 0 )
require( len( bs1 ) == 4 )
println("3rd")
require( flat(las1) == Nil )
require( flat(las2) == is )
println("4th")
require( sum(is) == 15 )
require( sum(flat(las2)) == sum(is) )
println("5th")
require( rev( bs1 ) == List( true, false, true, true ) )
require( rev( bs2 ) == bs2 )
println("6th")
require( !even( is ) )
require( even( bs1 ) )
require( even( las1 ) )
}
package ch.hepia.scala
/*
* Implémenter les fonctions suivantes en suivant les commentaires.
*/
object Predicates {
type P[A] = A=>Boolean
/*
* La méthode 'not' retourne un nouveau prédicat dont le résultat
* est toujours la négation du résultat de l'argument.
*/
def not[A]( p: A =>Boolean ): A =>Boolean = { a:A =>
!p(a)
}
/*
* La méthode 'and' retourne un nouveau prédicat dont le résultat
* est toujours la conjonction des résultats des deux arguments.
*/
def and[A](p1: A =>Boolean, p2: A =>Boolean ): A =>Boolean = { a:A =>
p1(a)&&p2(a)
}
/*
* La fonction 'or' retourne un nouveau prédicat dont le résultat
* est toujours la disjonction des résultats des deux arguments.
*/
def or[A](p1: A =>Boolean, p2: A =>Boolean ): A =>Boolean = { a:A =>
p1(a)||p2(a)
}
/*
* La fonction 'exists' retourne un nouveau prédicat dont le
* résultat est vrai si au moins un des prédicat de l'argument est
* vrai.
*/
def exists[A]( ps: List[A =>Boolean] ): A =>Boolean = { a:A =>
@scala.annotation.tailrec
def existRec(rest: List[P[A]], a: A): Boolean = rest match {
case Nil => false
case h :: _ if h(a) => true
case _ :: t => existRec(t, a)
}
existRec(ps, a)
}
/*
* La fonction 'forall' retourne un nouveau prédicat dont le
* résultat est vrai si et seulement si tous les prédicats de
* l'argument sont vrais.
*/
def forall[A]( ps: List[A =>Boolean] ): A =>Boolean = { a:A =>
@scala.annotation.tailrec
def forAllRec(rest: List[P[A]], a:A): Boolean = rest match{
case Nil => true
case h :: _ if !h(a) => false
case _ :: t => forAllRec(t, a)
}
forAllRec(ps, a)
}
}
package ch.hepia.scala
/* Implémentez les fonctions suivantes. Vous ne pouvez utiliser que les
* méthode de 'List' vues dans les exercices précédents.
*/
object HKFunc {
/* La fonction 'map' applique une fonction 'f' sur chaque élément de
* la liste 'as'. La liste résultat doit avoir la même longueur que
* l'argument.
*/
def map[A,B]( as: List[A] )( f: A=>B ): List[B] = {
@scala.annotation.tailrec
def applyOnHead(rec: List[A], acc: List[B]): List[B] = rec match {
case Nil => acc
case a :: tail => applyOnHead(tail, f(a)::acc)
}
Serie3.rev(applyOnHead(as, List.empty))
}
/* La fonction 'filter' utilise le prédicat 'f' pour déterminer quel
* élément garder. Le résultat peut être vide, mais l'ordre doit
* être préservé.
bbb */
def filter[A]( as: List[A] )( f: A=>Boolean ): List[A] = {
@scala.annotation.tailrec
def applyOnHead(rec: List[A], acc: List[A]): List[A] = rec match {
case Nil => acc
case a :: tail if f(a) => applyOnHead(tail, a::acc)
case a :: tail if !f(a) => applyOnHead(tail, acc)
}
Serie3.rev(applyOnHead(as, List.empty))
}
/* Réduit une liste 'as' en utilisant une opération binaire 'f'. On
* supposera que 'as' n'est pas vide.
*/
def reduce[A]( as: List[A] )( f: (A,A)=>A ): A = {
@scala.annotation.tailrec
def reduce2Head(rec: List[A], acc: A): A = rec match{
case Nil => acc
case b :: tail => reduce2Head(tail, f(b, acc))
}
reduce2Head(as.tail, as.head)
}
/* Transforme une fonction 'f' en une fonction s'appliquant sur une
* liste. Utiliser la fonction 'map' définie ci-dessus
*/
def lift[A,B]( f: A=>B ): List[A]=>List[B] = { (lstA: List[A]) => map(lstA)(f) }
/* DIFFICILE. Transforme une liste 'as' au moyen de la fonction 'f'.
* Cette fonction est appliquée à chaque élément de 'as' pour
* produire une nouvelle liste (qui peut être vide). Le résultat est
* la concaténation de chaque nouvelle liste en respectant l'ordre.
*/
def bind[A,B]( as: List[A] )( f: A=>List[B] ): List[B] = {
Serie3.flat(map(as)(f))
}
}
package ch.hepia.tpscala
/* Implémentez les fonctions suivantes.
*/
object Collect {
case class Album( title: String, artist: String, year: Int )
case class Duration( minutes: Int, seconds: Int ) {
def +(that: Duration): Duration = {
var min = this.minutes + that.minutes
var sec = (this.seconds+that.seconds)
if(sec > 60) {
min+=1
sec-=60
}
Duration(min, sec)
}
}
case class Track( title: String, duration: Duration )
val albums = List(
Album( "Mit Gas", "Tomahawk", 2003 ),
Album( "Pork Soda", "Primus", 1993 ),
Album( "Brown Album", "Primus", 1997 ),
Album( "Distraction Pieces", "Scroobius Pip", 2011 )
)
val tracks = Map(
"Mit Gas" -> List(
Track( "Mayday", Duration( 3, 32 ) )
),
"Pork Soda" -> List(
Track( "DMV", Duration( 4, 58 ) ),
Track( "Mr. Krinkle", Duration( 5, 27 ) )
),
"Brown Album" -> List(
Track( "Fisticuffs", Duration( 4, 25 ) ),
Track( "Camelback Cinema", Duration( 4, 0 ) ),
Track( "Kalamazoo", Duration( 3, 31 ) )
),
"Distraction Pieces" -> List(
Track( "Let 'Em Come", Duration( 4, 25 ) ),
Track( "Domestic Silence", Duration( 3, 58 ) )
)
)
/* Retourne la liste de morceaux associés à un artiste */
def tracksOf( artist: String ): List[Track] = {
albums.filter{ a => a.artist == artist}.map{ a => a.title}.flatMap(tracks)
}
/* Retourne la liste de tous les morceaux de moins de 4 minutes */
def shortTracks: List[Track] = {
tracks.flatMap(_._2.filter(_.duration.minutes < 4)).toList
}
/* Retourne les titres des morceaux antérieurs à une année */
def titlesBefore( year: Int ): List[String] = {
albums.filter(_.year<year).map(_.title).flatMap(tracks).map(_.title)
}
/* Calcule la durée totale de tous les morceaux disponibles.
REMARQUE: ont veut que les secondes soient inférieures à 60 mais les
minutes peuvent dépasser ce total.
*/
def totalDuration: Duration = {
tracks.values.flatten.map(_.duration).reduce(_+_)
}
}
package ch.hepia.scala
import org.scalatest.funsuite.AnyFunSuite
import Predicates._
class PredicatesSuite4 extends AnyFunSuite {
val big = (_:Int) >= 100
val even = (_:Int) % 2 == 0
val small = not[Int]( big )
val bae = and[Int]( big, even )
val boe = or[Int]( big, even )
test("Predicate Evaluation") {
assert( big(200) )
assert( ! big(19) )
assert( even(200) )
assert( ! even(201) )
}
test("Predicate negation") {
assert( small(19) )
assert( !small( 200 ) )
}
test("Predicate AND") {
assert( bae( 200 ) )
assert( !bae( 201 ) )
}
test("Predicate OR") {
assert( boe( 201 ) )
assert( !boe( 19 ) )
}
val mul3 = (_:Int ) % 3 == 0
val ps = List( big, even, mul3 )
test("Predicates FORALL") {
assert( forall[Int]( ps )( 402 ) )
assert( ! forall[Int]( ps )( 200 ) )
}
test("Predicates EXISTS") {
assert( exists[Int]( ps )( 18 ) )
assert( ! exists[Int]( ps )( 1 ) )
}
}
package ch.hepia.scala
import org.scalatest.funsuite.AnyFunSuite
import HKFunc._
class HKFunc5Suite extends AnyFunSuite {
val i0 = List[Int]()
val is = List( 1, 2, 3, 4 )
test("map") {
assert( map( i0 )(_ + 1 ) == i0 )
assert( map( is )(_ + 1 ) == List( 2, 3, 4, 5 ) )
assert( map( is )(_ * 2 ) == List( 2, 4, 6, 8 ) )
}
test("filter") {
assert( filter( i0 )(_ % 2 == 0 ) == i0 )
assert( filter( is )(_ % 2 == 0 ) == List( 2, 4 ) )
}
test("reduce") {
assert( reduce( is )( _ + _ ) == is.sum )
assert( reduce( is )( _ * _ ) == 24 )
}
test("lift") {
val f = (_:Int) + 1
val g = (_:Int) * 2
val id = lift[Int,Int]( identity )
assert( id(i0) == i0 )
assert( id(is) == is )
val h1 = lift( f andThen g )
val h2 = lift(f) andThen lift(g)
assert( h1(i0) == h2(i0) )
assert( h1(is) == h2(is) )
}
test("bind") {
val k = (i:Int) => if( i%2 == 0 ) List( -i, i ) else Nil
val l = (i:Int) => List( i, i )
assert( bind( i0 )( k ) == i0 )
assert( bind( is )( k ) == List( -2, 2, -4, 4 ) )
assert( bind( is )( l ) == List( 1, 1, 2, 2, 3, 3, 4, 4 ) )
}
}
package ch.hepia.tpscala
import org.scalatest.funsuite.AnyFunSuite
import Collect._
class Collect6Suite extends AnyFunSuite {
test( "tracksOf" ) {
assert( tracksOf("Justin Bieber").isEmpty )
assert( tracksOf("Tomahawk") == List( Track( "Mayday", Duration( 3, 32 ) ) ) )
assert( tracksOf("Primus").size == 5 )
}
test( "shortTracks" ) {
assert(
shortTracks.toSet == Set(
Track( "Mayday", Duration( 3, 32 ) ),
Track( "Kalamazoo", Duration( 3, 31 ) ),
Track( "Domestic Silence", Duration( 3, 58 ) )
)
)
}
test( "titlesBefore" ) {
assert( titlesBefore( 1928 ).size == 0 )
assert( titlesBefore( 2020 ).size == 8 )
assert(
titlesBefore( 2000 ).toSet == Set(
"DMV",
"Mr. Krinkle",
"Fisticuffs",
"Camelback Cinema",
"Kalamazoo"
)
)
}
test( "totalDuration" ) {
assert( totalDuration == Duration( 34, 16 ) )
}
}
File deleted
*~
target/
# Default ignored files
/workspace.xml
\ No newline at end of file
<component name="ProjectCodeStyleConfiguration">
<state>
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
</state>
</component>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="JavaScriptSettings">
<option name="languageLevel" value="ES6" />
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_13" default="false" project-jdk-name="13 (2)" project-jdk-type="JavaSDK" />
</project>
\ No newline at end of file