Estoy interesado en escribir una función eficiente de Haskell triangularize :: [a] -> [[a]]
que tome una lista (quizás infinita) y la "triangularice" en una lista de listas. Por ejemplo, triangularize [1..19]
debería volver
[[1, 3, 6, 10, 15]
,[2, 5, 9, 14]
,[4, 8, 13, 19]
,[7, 12, 18]
,[11, 17]
,[16]]
Por eficiente, quiero decir que quiero que se ejecute a O(n)
tiempo donde n
está la longitud de la lista.
Tenga en cuenta que esto es bastante fácil de hacer en un lenguaje como Python, porque agregar al final de una lista (matriz) es una operación de tiempo constante. Una función de Python muy imprescindible que logra esto es:
def triangularize(elements):
row_index = 0
column_index = 0
diagonal_array = []
for a in elements:
if row_index == len(diagonal_array):
diagonal_array.append([a])
else:
diagonal_array[row_index].append(a)
if row_index == 0:
(row_index, column_index) = (column_index + 1, 0)
else:
row_index -= 1
column_index += 1
return diagonal_array
Esto surgió porque he estado usando Haskell para escribir algunas secuencias "tabl" en la Enciclopedia en línea de secuencias enteras (OEIS), y quiero poder transformar una secuencia ordinaria (unidimensional) en un (2- dimensional) secuencia de secuencias exactamente de esta manera.
Quizás haya alguna forma inteligente (o no tan inteligente) de foldr
sobrepasar la lista de entrada, pero no he podido resolverlo.
foldr
lo que te gusta unfoldr (Just . combWith comb)
para listas infinitas. Por desgracia, como he mencionado en mi respuesta combWith
es O (n), por lo tanto, la respuesta aceptada splitAt
es significativamente más eficiente.