;;; Rangarajan Krishnamoorthy, Octo 10, 2026
;;; Run-length-encoding
;;; Code generated by ChatGPT (GPT 5.6 Medium) and Claude (Opus 5.5 Medium)


;;; Encode - ChatGPT
(defun run-length-encode (list &key (test #'eql))
  "Encode consecutive equal elements of LIST as (count value) pairs."
  (loop with result = '()
        with current = nil
        with count = 0
        for item in list
        do (if (and (> count 0)
                    (funcall test item current))
               (incf count)
               (progn
                 (when (> count 0)
                   (push (list count current) result))
                 (setf current item
                       count 1)))
        finally
           (when (> count 0)
             (push (list count current) result))
           (return (nreverse result))))

;;; Decode - ChatGPT
(defun run-length-decode (encoded)
  "Decode a list of (count value) pairs produced by RUN-LENGTH-ENCODE."
  (loop for (count value) in encoded
        append (make-list count :initial-element value)))

;;;; Encode - Claude
(defun encode (sequence &key (test #'eql))
  (let ((runs '()))
    (map nil (lambda (x)
               (if (and runs (funcall test (cdar runs) x))
                   (incf (caar runs))
                   (push (cons 1 x) runs)))
         sequence)
    (nreverse runs)))

;;;; Decode - Claude
(defun decode (runs &key (result-type 'list))
  (let ((result (make-sequence result-type
                               (loop for (count) in runs
                                     do (check-type count (integer 0))
                                     sum count))))
    (loop for (count . element) in runs
          for start = 0 then end
          for end = (+ start count)
          do (fill result element :start start :end end))
    result))



;;;;; Examples
(run-length-encode '(a a a b b c a))
;; => ((3 A) (2 B) (1 C) (1 A))

(run-length-decode '((3 A) (2 B) (1 C) (1 A)))
;; => (A A A B B C A)

(run-length-encode '())        ;; => NIL
(run-length-encode '(x))       ;; => ((1 X))

(run-length-encode '("apple" "apple" "banana") :test #'equal)
;; => ((2 "apple") (1 "banana"))

(run-length-encode '(#\a #\a #\b #\c #\c #\c))
;; => ((2 #\a) (1 #\b) (3 #\c))

(run-length-decode '((2 #\a) (1 #\b) (3 #\c)))
;; => (#\a #\a #\b #\c #\c #\c)

(encode '(a a a b b c a))
;; => ((3 . A) (2 . B) (1 . C) (1 . A))

(decode '((3 . A) (2 . B) (1 . C) (1 . A)))
;; => (A A A B B C A)