(in-package :cl-user)

(defun fun (x)
  (list 3 (expt (car x) 2)))

(defmacro nil! (var)
  (list 'setq var nil))

(defun longer-than (x y)
  (> (length x) (length y)))

(defun addlength (x)
  (cons (length x) x))

;;(defun crank-call (caller callee)
;;  '(hello callee this is caller calling))

(defun double (n)
  (* n 2))

(defun quad (n)
  (double (double n)))

(defun stooge (larry moe curly)
  (list larry (list moe curly) curly 'larry))

(defun ms (x)
  (list (second x) (first x)))

(defun if-test (x)
  (if (symbolp x) 
      (list '(what the fuck?))
      (list '(fuck the world!))))

(defun cond-test (x)
  (cond ((> x 0) x)
	((< x 0) (- x))))
  

(defun variable-scope-test (x)
  (setf x (+ x 2)))

(defun intersect2 (x y)
  (intersection x y))

(defun union2 (x y)
  (union x y))

(defun diff2 (x y)
  (set-difference x y))

(defun export_list ()
  (setf *assoc-list1* '((key1 . val1)
			(key2 . val2)
			(key3 . val3))))

(defun assoc1 (x)
  (cdr (assoc x *assoc-list1*)))

(defun rassoc1 (x)
  (car (rassoc x *assoc-list1*)))

(defun export_list2 ()
  (setf *list2* '((key1 valX val10 val11)
		  (key2 valX val20 val21))))

(defun set-xor (x y)
  (set-exclusive-or (rest (assoc x *list2*)) (rest (assoc y *list2*))))

;;; (remove-dups '(a a b c))
(defun remove-dups (x)
  (remove-duplicates x))

(defun substt (F G)
  (let ((y '(a b c)))
    (subst G F y)))

(defun let-test (x y)
  (let ((a 1)
	(b 2))
    (+ a b x y)))

;;; CL-USER> (subliss '(A . X) '(B . Y))
;;; (X Y C)
(defun subliss (F G)
  (let ((y '(A B C))
	(final-list (cons F (list G)))
	)
;;    (sublis '((A . X) (B . Y) (C . Z)) y)))
    (sublis final-list y)))
;;    (listp final-list)))

;;;· EQ is the fastest equality test: It compares addresses. Experts use
;;;it to compare symbols quickly, and to test whether two cons cells
;;;are physically the same object. It should not be used to compare
;;;numbers.
;;;· EQL is like EQ except it can safely compare numbers of the same
;;;type, such as two integers or two floating point numbers. It is the
;;;default equality test in Common Lisp.
;;;· EQUAL is the predicate beginners should use. It compares lists
;;;element by element; otherwise it works like EQL.
;;;· EQUALP is more liberal than EQUAL: It ignores case distinctions
;;;in strings, among other things.
;;;· = is the most efficient way to compare numbers, and the only way
;;;to compare numbers of disparate types, such as 3 and 3.0. It only
;;;accepts numbers.

(defun member-equal (x)
  (let ((l '((3 kupa) (5 karo) (as maca))))
    (member x l :test #'equal)))

(defun remove-equal (x)
  (let ((l '((3 kupa) (5 karo) (as maca))))
    (remove x l :test #'equal)))


(defun squ (x)
  (* x x))

;; (mapcar-test #'squ)
;; (1 4 9)
(defun mapcar-test (x)
  (let ((y '(1 2 3)))
    (mapcar x y)))

(defun mapcar-test2 ()
  (mapcar #'(lambda (n) (* n n)) '(1 2 3)))

;; also, (setf fn #'cons) etc.

;; CL-USER> (my-assoc 'A)
;; (A 1)
(defun my-assoc (key)
  (let ((y '((A 1) (B 2) (C 3))))
    (find-if #'(lambda (entry)
		 (equal key (first entry)))
	     y)))


;;CL-USER> (my-assoc-remove-if 'A)
;;((B 2) (C 3))
;; see also remove-if-not
(defun my-assoc-remove-if (key)
  (let ((y '((A 1) (B 2) (C 3))))
    (remove-if #'(lambda (entry)
		  (equal key (first entry)))
	      y)))

;; CL-USER> (reducee)
;; 6
(defun reducee ()
  (let ((y '(1 2 3)))
    (reduce #'+ y)))

;; CL-USER> (everyy)
;; T
(defun everyy ()
  (let ((y '(1 2 3 4 5)))
       (every #'numberp y)))

;; CL-USER> (everyyy)
;; NIL
;; also, (every #'> '(10 20 30 40) '(1 2 3 4))
(defun everyyy ()
  (let ((y '(1 2 3 4 5)))
       (every #'oddp y)))

;; (trace everyyy), (untrace everyyy)


;; CL-USER> (map-car2)
;; (11 22 33)
(defun map-car2 ()
  (let ((y '(1 2 3))
	(x '(10 20 30)))
    (mapcar #'+ y x)))

;; (setf pred (make-greater-than-predicate 3))
;; (funcall pred 2) => nil
;; (funcall pred 4) => t
(defun make-greater-than-predicate (n)
  #'(lambda (x) (> x n)))

;; RECURSION

;; compares first if its odd, returns.
;; double-test tail recursion
(defun anyoddp (x)
  (cond ((null x) nil)
	((oddp (first x)) t)
	(t (anyoddp (rest x)))))

;; augmented tail recursion 
;; means accumulation of recursive data
;; CL-USER> (count-slices '(A B C))
;; 3
(defun count-slices (x)
  (cond ((null x) 0)
	(t (+ 1 (count-slices (rest x))))))

;; list-consing recursion
;; constructs(cons) list every time
(defun laugh (n)
  (cond ((zerop n) nil)
	(t (cons ’ha (laugh (- n 1))))))

;; binary tree gezelim
;; CL-USER> (atoms-to-q '(A B (C D (E))))
;; (Q Q (Q Q (Q)))
(defun atoms-to-q (x)
  (cond ((null x) nil)
	((atom x) 'q)
	(t (cons (atoms-to-q (car x))
		 (atoms-to-q (cdr x))))))


;; loop-infinitely for (rest equals nil)
(defun any-7-p (x)
  (cond ((equal (first x) 7) t)
	(t (any-7-p (rest x)))))

(defun flattenn (x result)
  (cond ((null x) nil)
	((atom x) (list x))
	(t (append (flattenn (car x) result)
		   (flattenn (cdr x) result)))))

;; INPUT/OUTPUT
(defun 0utput ()
  (progn
    (format t "xxx newline~&this is newline")
    (format t "this is a S-exp: ~S" 'cemisgezek)))


;; > (test "Hi, mom")
;; With escape characters: "Hi, mom"
;; Without escape characters: Hi, mom
;; NIL
(defun 0utput2 (x)
  (format t "~&With escape characters: ~S" x)
  (format t "~&Without escape characters: ~A" x))



(defun draw-line ()
  (format t "~&---------------------"))

(defun draw-three (x)
  (format t "~&  ~A  |  ~A  |  ~A~%" 
	  (filter (first x)) (filter (second x)) (filter (third x))))


(defun filter (x)
  (cond ((equal x nil) " ")
	(t x)))

(defun draw-three2 (x)
  (format t "~&  ~A  |  ~A  |  ~A~%"
	  (first (filter2 x)) (second (filter2 x)) (filter2 (third x))))

(defun filter2 (x)
  (sublis '((nil . "")) x))


;; CL-USER> (draw-board '(X 0 NIL X 0 NIL X 0 NIL))
;;   X  |  0  |  
;;---------------------
;;  X  |  0  |   
;;---------------------
;;  X  |  0  |   
(defun draw-board (x)
  (draw-three2 x)
  (draw-line)
  (draw-three (nthcdr 3 x))
  (draw-line)
  (draw-three (nthcdr 6 x)))


;; read input
(defun what-da ()
  (format t "~&enter number:")
  (let ((x (read)))
    (format t "~&entered: ~A" x)))

(defun hashh()
  (let ((gee (make-hash-table)))
;  (setf gee (make-hash-table))
  (setf (gethash 'evrim gee) "i am your worst nightmare!")
  (format t "HASH VALUE: ~A~%" (gethash 'evrim gee))
  (describe gee)))

(defmacro simple-incf (var)
  (list 'setq var (list '+ var 1)))

(defmacro set-zero (&rest variables)
  `(progn ,@(mapcar #'(lambda (var)
			(list 'setf var 0))
		      variables)
	  '(zeroed ,@variables)))


;; DECLARE special
;; (setf x 2)
;; declaretest => 2
(defun declaretest ()
  (let ((x 1))
    (locally (declare (special x))
      x)))