Longest decreasing sequence in Lisp

可紊 提交于 2019-12-02 02:16:33

With contiguous subsequences, it's easy. Except I don't lisp, so I have to explain it in words.

  1. Call a recursive helper, with additional arguments a) longest found so far b) length of that c) current subsequence d) length thereof. Initially these are () 0 () 0.
  2. While head of list is even, recur on tail.
  3. Start current with the first odd encountered, recur on tail.
  4. If head is even, or head is not smaller than the previous element, the current sequence stops. Compare its length to the previously found longest sequence. If current is longer, it becomes the new longest, else forget current. Go to 2.

When the end of the list is reached, the longer of the two remembered lists is the answer.

You could do this in one stage using recursion (which would be faster & more efficient than the method I'm about to suggest), but it may be more readable, modular, and simpler to code if you generate all of the possible solutions first, filter by the ones that are valid, and then return the best of those solutions.

To do it this way, you'll need a generator & mapping function (I'd suggest two nested maplist's for this problem), a filter function (write this one; decreasing odd; then look at lisp's 'remove-if-not funciton), and a reducing function (return the best solution (longest list) from the filtered ones).

There's a section in SICP that discusses this style of approach: http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-15.html#%_sec_2.2

A signal-processing engineer would find it natural to conceptualize these processes in terms of signals flowing through a cascade of stages...

Will Ness

The algorithm as in Daniel's answer translated into Haskell, with some tweaks:

longest_sub xs = g2 xs [] 0 
  where
    g2 [] a _ = a
    g2 (x:t) a i  
         | even x    = g2 t a i 
         | otherwise = g4 t [x] 1
      where
        g4 [] b j = if j>i then reverse b else reverse a
        g4 xs@(x:t) b j            
             | even x || x >= head b
                         = if j>i then g2 xs b j 
                                  else g2 xs a i 
             | otherwise = g4 t (x:b) (j+1)

In Common Lisp:

(defun longest (xs)
  (prog  ((a nil) (i 0) b j x)                  ; var decls
      G2  (if (null xs) (return (reverse a)))   ; code
          (setf x (car xs) xs (cdr xs))
          (if (evenp x)
              (go G2))
      G3  (setf b (list x) j 1)
      G4  (if (null xs)
              (if (> j i)
                  (return (reverse b))
                  (return (reverse a))))
          (setf x (car xs) xs (cdr xs))
          (when (evenp x)
              (if (> j i) (setf a b i j))
              (go G2))
          (when (>= x (car b))
              (if (> j i) (setf a b i j))
              (go G3))
          (setf b (cons x b) j (+ j 1))
          (go G4)))

Function call is a glorified GOTO after all, isn't it?

see also: prog doc page.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!