Ich bin daran interessiert, eine effiziente Haskell-Funktion zu schreiben triangularize :: [a] -> [[a]]
, die eine (möglicherweise unendliche) Liste in eine Liste von Listen "trianguliert". Zum Beispiel triangularize [1..19]
sollte zurückkehren
[[1, 3, 6, 10, 15]
,[2, 5, 9, 14]
,[4, 8, 13, 19]
,[7, 12, 18]
,[11, 17]
,[16]]
Mit effizient meine ich, dass ich möchte, dass es O(n)
rechtzeitig ausgeführt wird, wo n
die Länge der Liste ist.
Beachten Sie, dass dies in einer Sprache wie Python recht einfach ist, da das Anhängen an das Ende einer Liste (eines Arrays) eine konstante Zeitoperation ist. Eine sehr wichtige Python-Funktion, die dies erreicht, ist:
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
Dies ist darauf zurückzuführen, dass ich Haskell verwendet habe, um einige "tabl" -Sequenzen in der Online-Enzyklopädie der ganzzahligen Sequenzen (OEIS) zu schreiben , und ich möchte in der Lage sein, eine gewöhnliche (eindimensionale) Sequenz in eine (2-) Sequenz umzuwandeln dimensionale) Sequenz von Sequenzen auf genau diese Weise.
Vielleicht gibt es eine clevere (oder nicht so clevere) Möglichkeit, foldr
die Eingabeliste zu überschreiten, aber ich konnte sie nicht klären.
foldr
Sie es unfoldr (Just . combWith comb)
für unendliche Listen mögen . Leider ist, wie ich unter meiner Antwort erwähnt habe, combWith
O (n), daher ist die akzeptierte Antwortverwendung splitAt
wesentlich effizienter.