Affichage des articles dont le libellé est testing. Afficher tous les articles
Affichage des articles dont le libellé est testing. Afficher tous les articles

S-99: P06, P07

Je continue la résolution des 99 problèmes en Scala. Au fur et à mesure que j'avance dans la résolutions de ces problèmes je me rends compte je fais beaucoup usage du pattern matching. Et cet épisode ne fait pas exception à la règle!


Le problème P06: Vérifier si une liste est un palindrome

C'est par là si vous voulez en savoir davantage sur le palindrome.
Exemple

scala> isPalindrome(List(1, 2, 3, 2, 1))
res0: Boolean = true


La solution à P06

Je suis rapidement arrivé à la solution suivante consistant à comparer la liste avec son inverse. J'ai ensuite cherché d'autres plus "efficace" mais je ne suis pas arrivé à trouver une solution plus "fonctionnelle" à mon goût.

def isPalindrome[T](xs: List[T]) = xs.reverse == xs


Le test de la solution

import org.specs2.mutable._

class P06Spec extends Specification {
  "P06.isPalindrome(xs)" should {    
    "return true" in {
      P06.isPalindrome(List()) must_== true
    }
    
    "return true" in {
      P06.isPalindrome(List(1)) must_== true
    }
    
    "return true" in {
      P06.isPalindrome(List(60, 60)) must_== true
    }
    
    "return true" in {
      P06.isPalindrome(List(3, 2, 1, 2, 3)) must_== true
    }
  }
}


Le problème P07: Mettre à plat une liste de listes

Il s'agit de mettre à plat une liste dont les constituants peuvent être des listes à leur tour. C'est pour le fun que nous écrivons cette fonction mais pas une nécessité car l'API des listes fournit une méthode permettant de mettre à plat une liste.
Exemple:

scala> flatten(List(List(1, 1), 2, List(3, List(5, 8))))
res0: List[Any] = List(1, 1, 2, 3, 5, 8)


La solution à P07

La solution utilise le pattern matching et la récursivité à fond!

  def flatten(xs: List[Any]): List[Any] = {
    xs match {
      case head :: tail => (head, tail) match {
        case (h: List[Any], t) => flatten(h) ++ flatten(t)
        case (h: Any, t) => h :: flatten(t)
      }
      case x => x
    }
  }


Le test de la solution

import org.specs2.mutable._

object P07Spec extends Specification {
  "P07.flatten(xs)" should {
    "return Nil" in {
      P07.flatten(Nil) must_== Nil
    }
    
    "return List(1)" in {
      P07.flatten(List(1)) must_== List(1)
    }
    
    "return List(1, 2)" in {
      P07.flatten(List(1, List(2))) must_== List(1, 2)
    }
    
    "return List(1, 2, 3, 4)" in {
      P07.flatten(List(1, List(2, 3), 4)) must_== List(1, 2, 3, 4)
    }
    
    "return List(1, 2, 3, 4, 5, 7, 8)" in {
      P07.flatten(List(1, List(2, 3), 4, List(5, List(6, List(7, 8))))) must_== List(1, 2, 3, 4, 5, 6, 7, 8)
    }
  }
}


Fin du voyage mes amis! A bientôt pour un autre épisode ;-)

S-99 : P02, P03, P04, P05

Avant d'aller plus loin laissez-moi vous dire que d'intéressantes discussions sont en cours sur la mailing liste du PSUG (Paris Scala User group). Je vous encourage à vous inscrire afin de prendre part aux échanges.
Nos oignons maintenant!

Le problème P02

Il s'agit en fait d'écrire une fonction qui retourne l'avant dernier élément d'une liste.
Voici l'exemple donné sur le site du S-99.

scala> penultimate(List(1, 1, 2, 3, 5, 8))
res0: Int = 5


La solution au P02

Voici une des solutions auxquelles je suis arrivé:

def penultimate[T](xs: List[T]) = {
      xs.reverse match {
        case _ :: x :: _ => Some(x)
        case _ => None
      }
    }


Le test de la solution à P02

import org.specs2.mutable._

class P02Spec extends Specification {
  "P02.penultimate(List())" should {
    
    "return None" in {
      P02.penultimate(List()) must_== None
    }

    "return None" in {
      P02.penultimate(List(1)) must_== None
    }

    "return Some(2.5)" in {
      P02.penultimate(List(3.23, 2.4)) must_== Some(3.23)
    }

    "return Some(2)" in {
      P02.penultimate(List(1, 2, 3)) must_== Some(2)
    }

    "return Some(3)" in {
      P02.penultimate(List(1, 2, 3, 4)) must_== Some(3)
    }
  }
}

Le problème P03

Il s'agit d'écrire une fonction qui renvoie l'élément correspondant à un index donné.
Exemple:

scala> nth(2, List(1, 1, 2, 3, 5, 8))
res0: Int = 2


La solution à P03

Avant d'aller plus loin permettez moi de vous dire que cet exercice n'a rien de nécessaire car l'API des listes permet de récupérer l'élément à un index donné de la façon suivante:

val element = xs(index)
Maintenant l'une des solutions que j'ai pu avoir:
def nth[T](index: Int, xs: List[T]):Option[T] = {
    (index, xs) match {  
      case (_, Nil) => None
      case (0, head :: tail) => Some(head)
      case (_, head :: tail) if(index == -1 || index > (xs.length + 1)) => None
      case (_, head :: tail) => nth(index - 1, tail)
    }
  }
Remarquez l'usage du pattern matching sur le tuple formé de l'index et de la liste.

Le test de la solution à P03

Enfin le test:

import org.specs2.mutable._

class P03Spec extends Specification {
  "P03.nth(index, xs)" should {
    
    "return None" in {
      P03.nth(-1, List(1, 3)) must_== None
    }

    "return Some(1)" in {
      P03.nth2(0, List(1, 3)) must_== Some(1)
    }

    "return Some(4)" in {
      P03.nth(2, List(2, 3, 4)) must_== Some(4)
    }

    "return None" in {
      P03.nth2(10, List(2, 3, 4, 5)) must_== None
    }

    "return None" in {
      P03.nth(0, List()) must_== None
    }    
  }
}

Le problème P04

Il s'agit encore une fois d'implémenter une fonctionnalité déjà présente dans l'API des listes mais c'est pour le fun: trouver le nombre d'éléments dans une liste
Exemple:

scala> length(List(1, 1, 2, 3, 5, 8))
res0: Int = 6

La solution au P04

Voici deux solutions à ce problème: l'une utilise la recursivité et l'autre la méthode foldLeft() de l'API des listes.

def lengthRecursive[T](xs: List[T]): Int = {
    xs match {
      case Nil => 0
      case head :: tail => 1 + lengthRecursive(tail)
    }
  }
  
def length[T](xs: List[T]) = {
  xs.foldLeft(0)((x, _) => x + 1)
}


Le test à la solution au P04

import org.specs2.mutable._

class P04Spec extends Specification {
  "P04.length(xs)" should {
    
    "return 0" in {
      P04.length(List()) must_== 0
    }

    "return 4" in {
      P04.length(List(1, 2, 3, 4)) must_== 4
    }

    "return 5" in {
      P04.length(List(1, 2, 3, 4, 5)) must_== 5
    }

    "return 7" in {
      P04.length(List(1, 2, 3, 4, 5, 6, 7)) must_== 7
    }
  }
}


Le problème P05

Il s'agit d'écrire une liste qui inverse une liste (pour info cette méthode existe déjà dans l'API des listes).
Exemple:

scala> reverse(List(1, 1, 2, 3, 5, 8))
res0: List[Int] = List(8, 5, 3, 2, 1, 1)


La solution au P05

def reverse[T](xs: List[T]):List[T] = xs match {
    case Nil => Nil
    case head :: tail => reverse(tail) :+ head
  }
  


Le problème P05

Enfin un petit test pour s'assurer que tout se passe bien!

import org.specs2.mutable._

class P05Spec extends Specification {
  "P05.reverse(xs)" should {
    
    "return Nil" in {
      P05.reverse(List()) must_== Nil
    }

    "return List(4, 3, 2, 1)" in {
      P05.reverse(List(1, 2, 3, 4)) must_== List(4, 3, 2, 1)
    }

    "return List(5, 4, 3, 2, 1)" in {
      P05.reverse(List(1, 2, 3, 4, 5)) must_== List(5, 4, 3, 2, 1)
    }

    "return List(7, 6, 5, 4, 3, 2, 1)" in {
      P05.reverse(List(1, 2, 3, 4, 5, 6, 7)) must_== List(7, 6, 5, 4, 3, 2, 1)
    }
  }
}


Conclusion

J'espère que les quelques solutions vous ont donné envie de suivre les prochains épisodes du S-99. Ne décrochez pas là les problèmes deviennent de plus en plus intéressants!
A bientôt!

S-99 : P01

J'ai entrepris de résoudre les problèmes du "S-99: Ninety-Nine Scala Problems", histoire de faire du Scala et peut-être de confronter mes solutions avec celles de mes lecteurs. Donc n'hésitez pas à poster vos solutions en commentaires! J'espère qu'à la fin de cette série de problèmes mon cerveau pensera mieux Scala ;-)


Le problème

Il s'agit d'écrire une fonction qui retourne le dernier élément d'une liste d'entiers.
Exemple fourni par le site:

scala> last(List(1, 1, 2, 3, 5, 8))
res0: Int = 8


Les solutions

Voici ma première implémentation:

def last1[T](xs: List[T]) = xs match {
    case List() => None
    case _ => Some(xs(xs.size - 1))
  }
Vous aurez remarqué que je ne renvoie pas directement le résultat mais plutôt un objet Option.
Voici une deuxième implémentation, plus courte, qui utilise la méthode headOption qui renvoit une Option avec sur l'élément de tête d'une liste. Remarquez que j'inverse d'abord la liste.
def last2[T](xs: List[T]): Option[T] = xs.reverse headOption
Enfin la version récursive:
def recursiveLast[T](xs: List[T]): Option[T] = xs match {
    case Nil => None
    case head :: Nil => Some(head)
    case head :: tail => recursiveLast(tail)
  }


Les tests

Voici le test de mes fonctions avec Specs2:

import org.specs2.mutable._

class P01Spec extends Specification {
  "P01.last1()" should {
    "return Some(8)" in {
      P01.last1(List(1, 1, 2, 3, 5, 8)) must_== Some(8)
    }

    "return Some(3)" in {
      P01.last1(List(1, 2, 3)) must_== Some(3)
    }

    "return Some(2.5)" in {
      P01.last1(List(3.23, 2.4, 5.0, 2.5)) must_== Some(2.5)
    }

    "return None" in {
      P01.last1(List()) must_== None
    }

    "return None" in {
      P01.last1(Nil) must_== None
    }
  }

  "P01.last2()" should {
    "return Some(8)" in {
      P01.last2(List(1, 1, 2, 3, 5, 8)) must_== Some(8)
    }

    "return Some(3)" in {
      P01.last2(List(1, 2, 3)) must_== Some(3)
    }

    "return Some(2.5)" in {
      P01.last2(List(3.23, 2.4, 5.0, 2.5)) must_== Some(2.5)
    }

    "return None" in {
      P01.last2(List()) must_== None
    }

    "return None" in {
      P01.last2(Nil) must_== None
    }
  }

  "P01.recursiveLast()" should {
    "return Some(8)" in {
      P01.recursiveLast(List(1, 1, 2, 3, 5, 8)) must_== Some(8)
    }

    "return Some(3)" in {
      P01.recursiveLast(List(1, 2, 3)) must_== Some(3)
    }

    "return Some(2.5)" in {
      P01.recursiveLast(List(3.23, 2.4, 5.0, 2.5)) must_== Some(2.5)
    }

    "return None" in {
      P01.recursiveLast(List()) must_== None
    }

    "return None" in {
      P01.recursiveLast(Nil) must_== None
    }
  }
}
The END!!! Mais avant de partir sachez que l'API de List offre une méthode (last) pour récupérer le dernier élément d'une liste et une autre (lastOption) pour récupérer un objet Option du dernier élément.
Bye!

© Nouhoum TRAORE.. Fourni par Blogger.