Functional way to get a matrix from text
- by Elazar Leibovich
I'm trying to solve some Google Code Jam problems, where an input matrix is typically given in this form:
2 3 #matrix dimensions
1 2 3 4 5 6 7 8 9 # all 3 elements in the first row
2 3 4 5 6 7 8 9 0 # each element is composed of three integers
where each element of the matrix is composed of, say, three integers. So this example should be converted to
#!scala
Array(
Array(A(1,2,3),A(4,5,6),A(7,8,9),
Array(A(2,3,4),A(5,6,7),A(8,9,0),
)
An imperative solution would be of the form
#!python
input = """2 3
1 2 3 4 5 6 7 8 9
2 3 4 5 6 7 8 9 0
"""
lines = input.split('\n')
print lines[0]
m,n = (int(x) for x in lines[0].split())
array = []
row = []
A = []
for line in lines[1:]:
for elt in line.split():
A.append(elt)
if len(A)== 3:
row.append(A)
A = []
array.append(row)
row = []
from pprint import pprint
pprint(array)
A functional solution I've thought of is
#!scala
def splitList[A](l:List[A],i:Int):List[List[A]] = {
if (l.isEmpty) return List[List[A]]()
val (head,tail) = l.splitAt(i)
return head :: splitList(tail,i)
}
def readMatrix(src:Iterator[String]):Array[Array[TrafficLight]] = {
val Array(x,y) = src.next.split(" +").map(_.trim.toInt)
val mat = src.take(x).toList.map(_.split(" ").
map(_.trim.toInt)).
map(a => splitList(a.toList,3).
map(b => TrafficLight(b(0),b(1),b(2))
).toArray
).toArray
return mat
}
But I really feel it's the wrong way to go because:
I'm using the functional List structure for each line, and then convert it to an array. The whole code seems much less efficeint
I find it longer less elegant and much less readable than the python solution. It is harder to which of the map functions operates on what, as they all use the same semantics.
What is the right functional way to do that?