Last active
August 29, 2015 14:12
-
-
Save volgar1x/dfb7e4312f72b5ec22dc to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Par Antoine CHAUVIN INFOB1 | |
*/ | |
object App { | |
import scala.util.Random | |
/** | |
* Vec represente un vecteur (x, y) | |
*/ | |
case class Vec(x: Int, y: Int) | |
/** | |
* Vec contient des fonctions auxiliaires en rapport aux vecteurs | |
*/ | |
object Vec { | |
/** | |
* Genere aleatoirement un vecteur unitaire | |
*/ | |
def sample(implicit rand: Random) = | |
Vec(rand.nextInt(3) - 1, rand.nextInt(3) - 1) | |
} | |
/** | |
* Mat represente une matrice (N, M) | |
*/ | |
class Mat[A](elems: Seq[Seq[A]]) { mat => | |
/** | |
* Loc represente un point precis (a, b) de la matrice | |
*/ | |
case class Loc(row: Int, col: Int) { | |
/** | |
* Recupere la valeur du point de la matrice | |
*/ | |
def get(): A = mat.get(row, col) | |
// de grands pouvoirs impliquent de grandes responsabilites | |
def apply(): A = get() | |
def unary_~ = get() | |
/** | |
* Dirige ce point grace a un vecteur | |
*/ | |
def map(vec: Vec): mat.Loc = mat.locate(row + vec.x, col + vec.y) | |
} | |
/** | |
* Recupere une point percis de la matrice | |
*/ | |
def get(i: Int, j: Int): A = elems(i)(j) | |
def apply(i: Int, j: Int): A = get(i, j) | |
/** | |
* Localise et isole une point precis de la matrice | |
* Cette fonction respecte le principe de toricite | |
*/ | |
def locate(i: Int, j: Int): this.Loc = | |
if (i < 0) locate(elems.length + i, j) | |
else if (i >= elems.length) locate(i % elems.length, j) | |
else if (j < 0) locate(i, elems(i).length + j) | |
else if (j >= elems(i).length) locate(i, j % elems(i).length) | |
else new Loc(i, j) | |
/** | |
* Transforme cette matrice par de nouvelles valeurs | |
*/ | |
def map(fn: this.Loc => A): Mat[A] = | |
new Mat[A](for (i <- 0 until elems.length) yield | |
for (j <- 0 until elems(i).length) yield | |
fn(locate(i, j))) | |
/** | |
* Transforme cette matrice par de nouvelles valeurs deja presentes dans la matrice | |
*/ | |
def flatMap(fn: this.Loc => this.Loc): Mat[A] = this map { fn(_).get() } | |
/** | |
* Multiplie cette matrice | |
*/ | |
def multiply(x: A)(implicit n: Numeric[A]) = this map { loc => n.times(~loc, x) } | |
def *(x: A)(implicit n: Numeric[A]) = multiply(x) | |
/** | |
* Genere une representation humaine de la matrice | |
*/ | |
override def toString: String = | |
elems map { _.mkString("[", " ", "]") } mkString("[", "\n ", "]") | |
} | |
/** | |
* Mat contient des fonctions auxiliaires en rapport aux matrices | |
*/ | |
object Mat { | |
/** | |
* Genere une matrice vide de taille (M, N) | |
*/ | |
def apply[A: Numeric](rows: Int, cols: Int): Mat[A] = | |
new Mat[A](Seq.fill[A](rows, cols)(implicitly[Numeric[A]].zero)) | |
/** | |
* Genere une matrice vide carre de taille N | |
*/ | |
def square[A: Numeric](len: Int): Mat[A] = apply(len, len) | |
/** | |
* Genere une matrice unitaire de taille N | |
*/ | |
def unit[A](len: Int)(implicit n: Numeric[A]): Mat[A] = { | |
/** | |
* Genere une ligne de la matrice | |
*/ | |
def line(i: Int): Seq[A] = | |
List.fill(i)(n.zero) ++ // on genere d'abord les zeros "a gauche" du un | |
List(n.one) ++ // ensuite on ajoute le un | |
List.fill(len - i - 1)(n.zero) // et on genere les zeros restants "a droite" | |
// genere les colonnes de la matrice | |
val elems: Seq[Seq[A]] = for (i <- 0 until len) yield line(i) | |
new Mat[A](elems) | |
} | |
/** | |
* Genere une matrice aleatoire de taille (M, N) | |
*/ | |
def sample(rows: Int, cols: Int)(implicit rand: Random): Mat[Int] = | |
new Mat[Int](for (i <- 0 until rows) yield | |
for (j <- 0 until cols) yield | |
rand.nextInt()) | |
} | |
/** | |
* Fais converger aleatoirement une matrice | |
*/ | |
def converge[A](mat: Mat[A])(implicit rand: Random): Mat[A] = mat flatMap { _ map Vec.sample } | |
/** | |
* Point d'entree du programme | |
*/ | |
def main(args: Array[String]): Unit = { | |
/** | |
* Utilise une instance implicite de Random | |
*/ | |
implicit val rand = new Random | |
/** | |
* Comment se servir d'une matrice | |
*/ | |
val u = Mat.unit[Int](3) | |
println(u * 2) | |
/** | |
* Et maintenant, faisons converger 1000 fois une matrice (10, 10) | |
*/ | |
// on genere tout d'abord la matrice "graine" | |
val seed = Mat.sample(10, 10) | |
// on genere ensuite un flux de matrice constamment convergeant | |
val mats = Stream.iterate(seed) { converge(_) } | |
// on recupere enfin la 1000e matrice du flux convergeant | |
val mat = mats(1000) | |
println(mat) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment