;; P09 (**) Pack consecutive duplicates of list elements into sublists.
;; If a list contains repeated elements they should be placed in separate sublists.
;; * (pack '(a a a a b c c a a d e e e e))
;; ((A A A A) (B) (C C) (A A) (D) (E E E E))
(defun pack (x)
(%pack (catenate x (scan (list (gensym)))))) ; #z(a b c) => #z(a b c #:G1)
(defun %pack (x &aux acc)
(mapping ((a x)
(b (previous x (collect-first x))))
(if (eql a b)
(progn (push a acc) nil)
(setf acc (list a)))))))
(pack #z(a a a a b c c a a d e e e e))
;; P10 (*) Run-length encoding of a list.
;; Use the result of problem P09 to implement the so-called run-length encoding data compression method. Consecutive duplicates of elements are encoded as lists (N E) where N is the number of duplicates of the element E.
;; * (encode '(a a a a b c c a a d e e e e))
;; ((4 A) (1 B) (2 C) (2 A) (1 D)(4 E))
(defun encode (x)
(#M(lambda (x) (list (length x) (car x)))
(encode #z(a a a a b c c a a d e e e e))
;; P11 (*) Modified run-length encoding.
;; Modify the result of problem P10 in such a way that if an element has no duplicates it is simply copied into the result list. Only elements with duplicates are transferred as (N E) lists.
;; * (encode-modified '(a a a a b c c a a d e e e e))
;; ((4 A) B (2 C) (2 A) D (4 E))
(defun encode-modified (x)
(mapping ((e (pack x)))
(let ((length (length e))
(car (car e)))
(if (= 1 length)
(list length car)))))
(encode-modified #z(a a a a b c c a a d e e e e))