;; append two lists
;; why do you only need the type on x here?
(defun app (x y)
  (if (consp x)
      (cons (car x) (app (cdr x) y))
    y))

;; proving that app with nil returns orig list
;; acl2 rejects this version
(defthm nil-is-left-id-for-app1
  (equal x (app nil x)))

;; another (accpetable) try
(defthm nil-is-left-id-for-app2
  (equal (app nil x) x))

;; flatten a tree into a list of its leaves (left to right order)
(defun flatten (x)
  (if (consp x)
      (app (flatten (car x))
           (flatten (cdr x)))
    (list x)))

;; in a tree, change any leaf with a number to have the symbol 'int
(defun hit (x)
  (if (consp x)
      (cons (hit (car x))
            (hit (cdr x)))
    (if (integerp x)
        'int
      x)))

;; two example trees for testing our functions
(defconst *mytree1* (cons (cons 1 (cons 2 3)) (cons (cons 4 (cons 5 6)) 7)))
(defconst *mytree2* (cons (cons 1 (cons 'kathi 3)) (cons (cons 4 (cons 5 'wpi)) 7)))

;; thm : flatten and hit can be performed in either order
(defthm flatten-hit
  (equal (flatten (hit x))
         (hit (flatten x))))

;; thm : app distributes over hit
(defthm app-hit
  (equal (app (hit x) (hit y))
         (hit (app x y))))

;; Once hit, can flatten without having to hit again
;; fails
(defthm hit-flatten-hit
  (equal (hit (flatten (hit x)))
         (hit (flatten x))))

;; hitting only required once
(defthm hit-is-idempotent
  (equal (hit (hit x)) (hit x)))

;; with hit-is-idempotent, hit-flatten-hit passes
