আমরা উপ-লিনিয়ার সময়ে সূচি দিতে পারি এমন একটি কাঠামো তৈরি করে খুব দক্ষতার সাথে এটি করতে পারি।
কিন্তু প্রথম,
{-# LANGUAGE BangPatterns #-}
import Data.Function (fix)
আসুন সংজ্ঞায়িত করা যাক f
, তবে সরাসরি এটিকে কল করার পরিবর্তে এটিকে 'ওপেন পুনরাবৃত্তি' ব্যবহার করুন।
f :: (Int -> Int) -> Int -> Int
f mf 0 = 0
f mf n = max n $ mf (n `div` 2) +
mf (n `div` 3) +
mf (n `div` 4)
আপনি f
ব্যবহার করে একটি স্মরণীয় পেতে পারেনfix f
এটি আপনাকে পরীক্ষা করতে f
দেয় যা f
কল করে ক্ষুদ্র মূল্যবোধগুলির জন্য আপনার অর্থ কি তা বোঝায় , উদাহরণস্বরূপ:fix f 123 = 144
আমরা এটি সংজ্ঞায়িত করে স্মরণ করতে পারি:
f_list :: [Int]
f_list = map (f faster_f) [0..]
faster_f :: Int -> Int
faster_f n = f_list !! n
এটি উত্তমরূপে ভাল সম্পাদন করে এবং ও কী নিতে চলেছে তা প্রতিস্থাপন করে (n ^ 3) সময় ফলাফলগুলিকে স্মরণ করিয়ে দেয় time
তবে এর জন্য স্মৃতিযুক্ত উত্তর খুঁজে পেতে কেবল সূচকে লিনিয়ার সময় লাগে mf
। এর অর্থ এই যে ফলাফলগুলি:
*Main Data.List> faster_f 123801
248604
সহনীয়, তবে ফলাফলটি এর চেয়ে ভাল স্কেল করে না। আমরা আরও ভাল করতে পারি!
প্রথমে আসুন একটি অসীম গাছ নির্ধারণ করুন:
data Tree a = Tree (Tree a) a (Tree a)
instance Functor Tree where
fmap f (Tree l m r) = Tree (fmap f l) (f m) (fmap f r)
এবং তারপর আমরা এটি মধ্যে সূচক একটি উপায় নির্ধারণ করব, তাই আমরা সূচকের সাথে একটি নোড জানতে পারেন n
মধ্যে হে (লগ ঢ) সময় পরিবর্তে:
index :: Tree a -> Int -> a
index (Tree _ m _) 0 = m
index (Tree l _ r) n = case (n - 1) `divMod` 2 of
(q,0) -> index l q
(q,1) -> index r q
... এবং আমরা সুবিধাজনক হওয়ার জন্য প্রাকৃতিক সংখ্যায় পূর্ণ একটি গাছ পেতে পারি যাতে আমাদের সেই সূচকগুলি নিয়ে ঘুরতে হবে না:
nats :: Tree Int
nats = go 0 1
where
go !n !s = Tree (go l s') n (go r s')
where
l = n + s
r = l + s
s' = s * 2
যেহেতু আমরা সূচক করতে পারি, আপনি কেবল একটি গাছকে তালিকায় রূপান্তর করতে পারেন:
toList :: Tree a -> [a]
toList as = map (index as) [0..]
যা toList nats
দেয় তা যাচাই করে আপনি এতক্ষণ কাজটি পরীক্ষা করতে পারেন[0..]
এখন,
f_tree :: Tree Int
f_tree = fmap (f fastest_f) nats
fastest_f :: Int -> Int
fastest_f = index f_tree
উপরের তালিকার মতো ঠিক কাজ করে, তবে প্রতিটি নোডের সন্ধান করার জন্য লিনিয়ার সময় না দিয়ে লোগারিথমিক সময়ে এটি তাড়া করতে পারে।
ফলাফলটি যথেষ্ট দ্রুত:
*Main> fastest_f 12380192300
67652175206
*Main> fastest_f 12793129379123
120695231674999
আসলে এটি এত দ্রুত যে আপনি উপরের Int
সাথে যেতে পারেন এবং প্রতিস্থাপন করতে পারেন এবং Integer
প্রায় তাত্ক্ষণিকভাবে হাস্যকর আকারে বড় উত্তরগুলি পেতে পারেন
*Main> fastest_f' 1230891823091823018203123
93721573993600178112200489
*Main> fastest_f' 12308918230918230182031231231293810923
11097012733777002208302545289166620866358