You can do this quite easily in a few simple steps:
- First break the input into a
List of lines
- Then break each line into a
List of Strings
- Then convert each
String in the list to an Int
- And finally summarize this
List of Lists of Lists to a List of Arrays (using a simple state machine)
The state machine is quite simple.
- It first reads the number of lines in the next matrix and memorizes it
- It then reads in that number of lines to the current matrix
- After it has read the memorized number of lines it adds the current matrix to the list of read matrixes and goes back to step 1
The code will look something like this:
import io.Source
def input = Source.fromString(
"""|3
|1 2 1
|1 2 2
|1 2 3
|4
|1 2 3 1
|1 2 3 2
|1 2 3 3
|1 2 3 4""".stripMargin) // You would probably use Source.fromFile(...)
type Matrix = List[Array[Int]]
sealed trait Command
case object ReadLength extends Command
case class ReadLines(i: Int, matrix: Matrix) extends Command
case class State(c: Command, l: List[Matrix])
val parsedMatrixes = input.getLines().map(_.split(" ")).map(_.map(_.toInt)).foldLeft(State(ReadLength, List())) {
case (State(ReadLength, matrixes), line) => State(ReadLines(line(0), List()), matrixes)
case (State(ReadLines(1, currentMatrix), matrixes), line) => State(ReadLength,((line::currentMatrix).reverse)::matrixes)
case (State(ReadLines(i, currentMatrix), matrixes), line) => State(ReadLines(i - 1, line::currentMatrix), matrixes)
}.l.reverse
And gives you the following result:
parsedMatrixes: List[Matrix] =
List(
List(Array(1, 2, 1),
Array(1, 2, 2),
Array(1, 2, 3)),
List(Array(1, 2, 3, 1),
Array(1, 2, 3, 2),
Array(1, 2, 3, 3),
Array(1, 2, 3, 4)))
Please be aware that this cannot be the final solution because it does not have any error handling. And it does not free up its resources (closing the source).
fromFile(f).mkStringinstead offromFile(f).getLines.mkString?