Muszę obliczyć foo n = maximumBy (comparing p) [1..n]
, gdzie p :: Int -> Int
jest powolny. Ale wiem, że p n < n
dla wszystkich n > 0
i chcesz użyć tego faktu, aby przyspieszyć to obliczenie w następujący sposób: Obliczyć p x
dla x
począwszy od n
do 1
, zapamiętywanie bieżącego maksimum. Po osiągnięciu x
mniejszej lub równej bieżącemu maksimum wiem, że to maksimum musi być globalne i gotowe.Kod haskel Idiomatic upraszczający rekursję
Więc moja próba wygląda następująco:
foo n = go (0, 0) n where
go (c, _) 1 = c
go (c, c') !x = if c' >= x then c else go (c2, c'2) (x-1) where
x' = p x
(c2, c'2) = if c' >= x' then (c, c') else (x, x')
To działa, ale nie wygląda bardzo idiomatyczne. Dlatego szukam bardziej eleganckiego rozwiązania. Czy masz sugestie?
Pozbądź pary sprawiają, że '' iść xyn ... i chciałbym związać 'pn' do nazwy (DON nawet dać kompilatorowi szansę na przeliczenie go), w przeciwnym razie to bym zrobił. Prosty, jasny, wydajny. –
Dzięki, zamień parę tak, jak sugerujesz, zdecydowanie lepiej. W każdym razie, muszę przyznać, że zawaham się przed użyciem pozwolenia na wiązanie, ponieważ naprawdę nie wiem, czy w drugim dopasowywaniu wzorca, (p n) będzie obliczane dwa razy lub nie. Jeśli muszę usprawiedliwić mój kod, twierdzę, że Haskell jest z natury leniwy, co oznacza, że strategia oceny to "wezwanie po prawdę", a definicja "wezwanie po potrzebie" jest pamiętaną wersją nazwy wywoławczej ", to powinno być w porządku, nie? Ponieważ prawdą jest, że za pomocą wpuszczonego wiązania, jak sugerujesz, nie pozwól nikomu wątpić, dodałem Twoją sugestię poniżej mojej. – zurgl
Użyłbym 'gdzie'. 'go x y n | n == 1 || n <= y = x | pn> y = go n pn (n-1) | inaczej = odchodzenie xy (n-1) gdzie pn = pn'. –