; P08 Eliminate consecutive duplicates of list elements. ; If a list contains repeated elements they should be replaced with a ; single copy of the element. The order of the elements should not be changed. (def a (list "a" "a" "a" "a" "b" "c" "c" "a" "a" "d" "e" "e" "e" "e")) (func compress-iter (lst) (def out (list)) (for-each lst (if (or (empty? out) (not (eq? _item_ (last out)))) (redef out (append out _item_)))) out) ; use the type system/dynamic dispatch (func compress-typ (lst) (compress-typ lst (list))) ; empty lists (func compress-typ (lst :nil acc) acc) ; non-empty lists, combined with a branch ;(func compress-typ (lst :{:any} acc) ; (branch ; ((empty? acc) (compress-typ (rest lst) (list (first lst)))) ; ((not (eq? (first lst) (last acc))) (compress-typ (rest lst) (append acc (first lst)))) ; (#true (compress-typ (rest lst) acc)))) ; non-empty lists, non-empty accumulator (func compress-typ (lst :{:any} acc :{:any}) (if (eq? (first lst) (last acc)) (compress-typ (rest lst) acc) ; don't append (compress-typ (rest lst) (append acc (first lst))))) ; non-empty lists, empty accumulator (func compress-typ (lst :{:any} acc :nil) (compress-typ (rest lst) (list (first lst)))) ;(func extend (lst1 lst2) ; (reduce append lst2 lst1)) ; everything is an expression, so you could do this too ; not sure if you'd want to, though, as you're creating ; a list and then immediately killing it, which seems ; like it's probably wasteful in the interpreter ;(func compress-typ (lst :{:any} acc :{:any}) ; (compress-typ (rest lst) ; (extend ; acc ; (if (not (eq? (first lst) (last acc))) ; (list (first lst)))))) (print (->string a)) (print (->string (compress-iter a))) (print (->string (compress-typ a)))