2012-03-18 32 views
6

Hãy tưởng tượng bạn cần phải gấp trên một chuỗi, và muốn biết các giá trị trung gian tại một số điểm dọc theo dãy. Đây là những gì tôi đã sử dụng cho việc này:Mẫu gấp và lặp này là gì?

[a,b,c] = map fst . tail $ chain [g i, g j, g k] (zero, sequence) 

g :: Integer -> (a,b) -> (a,b) 

chain (f:fs) x = x : chain fs (f x) 
chain [] x = [x] 

Chức năng g tiêu thụ một phần nhất định một chuỗi đầu vào (chiều dài i, j, vv), bắt đầu với một số giá trị ban đầu và sản xuất kết quả của cùng một loại, để được đưa vào lời gọi tiếp theo. Tiêu thụ trình tự nhiều lần cho các độ dài khác nhau bắt đầu lại từ đầu và giá trị ban đầu giống nhau sẽ không hiệu quả, cả về thời gian và không gian thông minh.

Vì vậy, một mặt chúng tôi gấp qua chuỗi số nguyên này - các điểm tạm thời trên chuỗi; mặt khác, chúng tôi lặp lại chức năng này, g. Nó là gì? Tôi có thiếu cái gì cơ bản ở đây không? Điều này có thể được bằng cách nào đó thể hiện với tiết mục thường xuyên của nếp gấp, vv?

EDIT:   giải quyết:   ở trên chỉ đơn giản là

[a,b,c] = map fst . tail $ scanl (flip g) (zero, sequence) [i, j, k] 

thú vị như thế nào một sự lặp lại sửa đổi thực sự là gấp qua danh sách các bộ điều chỉnh.

+6

Về cơ bản bạn có nghĩa là scanl? http://www.haskell.org/hoogle/?hoogle=scanl – Marcin

+1

@Marcin ah, vâng, những thứ cơ bản. Chắc là đúng. Điều làm tôi bối rối là bản thân 'g' cũng gấp nếp theo thứ tự. Tôi đoán chức năng quét sẽ kết hợp '(zero, sequence)' với 'i' và quét qua danh sách' [i, j, k] 'trực tiếp ... Cảm ơn, sẽ thử điều đó! –

Trả lời

9

Hãy thử scanl: http://www.haskell.org/hoogle/?hoogle=scanl

scanl cũng tương tự như foldl, nhưng trả về một danh sách liên tiếp giảm giá trị từ bên trái:

scanl f z [x1, x2, ...] == [z, z `f` x1, (z `f` x1) `f` x2, ...] 

Lưu ý rằng

last (scanl f z xs) == foldl f z xs 
4

Để xây dựng trên bình luận Marcin của, về cơ bản bạn muốn:

intermediates = scanl step zero sequence 
map (\n -> intermediates !! n) [i, j, k] 

step không phải là g, nhưng thay vì chỉ là một phần của g rằng tiêu thụ một yếu tố duy nhất của danh sách sequence.

Ngoài ra, hãy chấp nhận Marcin là câu trả lời đúng.

+0

trình tự là rất lớn (tốt, * lớn *), và tôi chỉ cần hai trung gian và một cuối cùng. Toàn bộ điều này là để tiêu thụ không gian thấp hơn và cung cấp cho ghc một cơ hội để loại bỏ càng nhiều thứ càng tốt. Ngoài ra, tôi đã chấp nhận 5 phút trước khi đăng bài của bạn. :) Cảm ơn! –

+0

Nếu bạn biên dịch ở trên với tối ưu hóa GHC sẽ tự động thu thập rác thu thập kết quả trung gian mà bạn không sử dụng, do đó, nó sẽ chạy trong không gian liên tục. Nó không đắt hơn nếu bạn tự làm nếp gấp trung gian bằng tay. –

+0

Tôi có một nghi ngờ rằng '(!! n)' sẽ yêu cầu sự tồn tại của toàn bộ chuỗi vì nó phải bắt đầu đếm từ đầu. Nhưng tôi sẽ thử nó sau, cảm ơn.Mỗi giá trị trước đó là cần thiết để tạo ra giá trị tiếp theo; ngay cả khi nó không cần thiết nữa thì có rất nhiều hoạt động (gc), và bản thân danh sách vẫn sẽ được duy trì, vì vậy nó có thể không giải phóng được giá trị của mỗi nút khi nó đã bị ép buộc. Khi tính toán theo các bước chính xác thì điều gì đã tránh được, hy vọng. Tôi thực sự đã thấy một sự sụt giảm đáng kể kích thước không gian với cách tiếp cận của tôi. –

Các vấn đề liên quan