Tôi quan tâm đến việc viết một hàm Haskell hiệu quả triangularize :: [a] -> [[a]]
, lấy một danh sách (có lẽ là vô hạn) và "tam giác hóa" nó thành một danh sách các danh sách. Ví dụ, triangularize [1..19]
nên trả lại
[[1, 3, 6, 10, 15]
,[2, 5, 9, 14]
,[4, 8, 13, 19]
,[7, 12, 18]
,[11, 17]
,[16]]
Theo hiệu quả, tôi có nghĩa là tôi muốn nó chạy trong O(n)
thời gian mà n
độ dài của danh sách.
Lưu ý rằng điều này khá dễ thực hiện trong một ngôn ngữ như Python, bởi vì việc thêm vào cuối danh sách (mảng) là một hoạt động thời gian không đổi. Một hàm Python rất bắt buộc thực hiện điều này là:
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
Điều này xuất hiện bởi vì tôi đã sử dụng Haskell để viết một số chuỗi "tabl" trong Từ điển bách khoa toàn thư về chuỗi số nguyên (OEIS) và tôi muốn có thể chuyển đổi một chuỗi (1 chiều) thông thường thành một (2- chiều) thứ nguyên) trình tự các chuỗi theo cách chính xác.
Có lẽ có một số cách thông minh (hoặc không thông minh) để foldr
vượt qua danh sách đầu vào, nhưng tôi không thể sắp xếp nó ra.
foldr
bạn có thể thích unfoldr (Just . combWith comb)
cho danh sách vô hạn. Than ôi như tôi đã đề cập dưới câu trả lời của tôi combWith
là O (n) do đó câu trả lời được chấp nhận sử dụng splitAt
có hiệu quả hơn đáng kể.