Abraham
Abraham

Reputation: 11

Return the longest sequence of consecutive numbers from list in lisp

I am a lisp newbie. I'm trying to create a function in lisp that receives an unsorted list and the function has to sort de list and return a list with the longest sequence of numbers. Example: (2 1 8 9 3 11 10 20 12 21)(1 2 3 8 9 10 11 12 20 21) -> return (8 9 10 11 12)

I don't want to use the sort function and I have created 2 functions (With some help) to sort, but now I have no idea how I could find and return the longest sequence of numbers. I could go through the list but, how I can store the numbers and check if a list of consecutive numbers is longer than another?

This are my functions to sort

(defun sortOne (list)
  
  (let ((ca1 (car list)) (cd1 (cdr list)))
    (if (null cd1)
        list
        (let ((cd (sortOne cd1))) ; cd = sorted tail
          (let ((ca2 (car cd)) (cd2 (cdr cd)))
            (if (<= ca1 ca2)
                (cons ca1 cd)
                (cons ca2 (cons ca1 cd2))))))))

(defun sortAll (list)
  (if (null list)
      nil
      (let ((s (sortOne list)))
        (cons (car s) (sortAll (cdr s))))))

Hope someone can help me.

¡Thanks!

Upvotes: 0

Views: 105

Answers (2)

Gwang-Jin Kim
Gwang-Jin Kim

Reputation: 9865

(defun group-consecutives (l &optional (acc '()))
  (cond ((null l) (nreverse acc))
        ((and acc (= 1 (- (car l) (caar acc)))) (consecutives (cdr l) (cons (cons (car l) (car acc)) (cdr acc))))
        (t (consecutives (cdr l) (cons (list (car l)) (when acc (cons (nreverse (car acc)) (cdr acc))))))))

(defun longest-consecutive (l)
  (car (sort (consecutives (sort l #'<)) #'> :key #'length)))

(longest-consecutive '(2 1 8 9 3 11 10 20 12 21)) 
;;=> (8 9 10 11 12)

Probably the second function is easier to understand like this:

(defun sort-increasing (l)
  (sort l #'<))

(defun sort-groups-by-length (groups)
  (sort groups #'> #'length))

(defun longest-consecutive (l)
  (car (sort-groups-by-length (group-consecutives (sort-increasing l))))))))

Upvotes: 0

Abraham
Abraham

Reputation: 11

Tonight I managed to do it, but surely it is not the best solution, I would like to know how to use a lambda function or recursion to do it better.

 (defun listilla (lista)
  (setq lista (sort lista #'<))
  (setq lista1 (list (car lista)))
  (setq lista2 '())
  (loop for i from 0 to (- (length lista) 2) do
    (cond ((= (nth i lista) (- (nth (+ i 1) lista) 1))
        (push (nth (+ i 1) lista) (cdr (last lista1))))
        (t (push lista1 lista2)
        (setq lista1 (list (nth (+ i 1) lista)))
        )
        
    )
    )
    (push lista1 lista2)
    (setq masLargo (car lista2))
    (loop for i from 1 to (- (length lista2) 2) do
        (if (< (length (nth i lista2)) (length (nth (+ i 1) lista2)))
        (setq masLargo (nth (+ i 1) lista2))
        )
    )
    masLargo

 )
 (print (listilla '(23 15 6 5 78 4 77)))

Upvotes: 1

Related Questions