val m = List(List(1,2,3), List(4,5,6), List(7,8,9))
 
type Matrix = List[List[Int]]
type Str = List[Char]
 
val s: String = "1,2,3\n4,5,6\n7,8,9\n"
 
// "111,2,0"
// List( '1', '1', '1', ',', '2', ',', '0')
 
def split(delim: Char)(s: Str): List[Str] =
  s.foldRight(Nil:List[Str])((x,acc) =>
    acc match {
      case l :: ls => if (delim != x) (x :: l) :: ls else Nil :: acc
      case Nil => if (delim != x) (x::Nil)::Nil else Nil
    }
  )
 
split('\n')(s.toList)
// Str = List[Char]
def makeInt(s: Str): Int =
  s
    .foldRight("")(_ + _)
    .toInt
 
def readMatrix: String => Matrix =
  (((s: String) => s.toList)           // make String into List[Char] = Str
    andThen split('\n')          // separate a Str into List[Str], which produces separated lines
    andThen (_.map(split(',')))  // List[List[Str]] - map separation operation on each line, to produce List[List[Str]]
    andThen (_.map(_.map(makeInt))))
 
readMatrix(s)
 
def readMatrixFor(s: String): Matrix = {
  for (line <- split('\n')(s.toList)) // List[Str]
    yield for (elem <- split(',')(line))
      yield makeInt(elem)
}
readMatrixFor(s)
 
// for expressions.
 
List(1,2,3).map(_*2)
 
val l: List[Int] =
  for (x <- List(1,2,3))
    yield 2*x
 
List(1,2,3).filter(_ % 2 ==1).map(_+1)
 
for (x <- List(1,2,3) if x%2 == 1)
  yield x+1
 
// matrix where each element is a pair
val what: List[List[(Int,Int)]] =
  for (x <- List(1,2,3))
    yield
      for (y <- List(4,5,6))  // List[(Int,Int)]
        yield (x,y) // (Int,Int)
 
// just a flat list, not a matrix
val flat: List[(Int,Int)] =
for (x <- List(1,2,3);
     y <- List(4,5,6))
  yield (x,y)
 
val mat: List[List[Int]] = readMatrix(s)
/*
    1 2 3
    4 5 6
    7 8 9
 */
 
// how to multiply a matrix by a factor?
val factor = 2
 
for (line <- mat)
  yield for (elem <- line)
    yield elem*factor
 
mat.map(_.map(_*factor))
 
 
List(1,2,3).zip(List(4,5,6))
 
/*
    1 2 3       1 2 3      2 4 6
    4 5 6   +   4 5 6   =  8 10 12
    7 8 9       7 8 9      ...
 */
 
def addFor(m1: Matrix, m2: Matrix): Matrix =
  for (pair <- m1.zip(m2)) //List[(List[Int],List[Int])]
    yield for (p <- pair._1.zip(pair._2))
      yield p._1 + p._2
 
addFor(mat,mat)
 
def add(m1: Matrix, m2: Matrix): Matrix =
    m1
      .zip(m2)
      .map(pair => pair._1.zip(pair._2).map(p => p._1 + p._2))
 
add(mat,mat)