;----------- 3 задание

(defun replace ; заменяет все значения old_value на new_value в списке array
       (array old_value new_value)
       (cond 
            ((null array) nil)
            ((eql old_value (car array)) (cons new_value (replace (cdr array) old_value new_value)))
            (t (cons (car array) (replace (cdr array) old_value new_value)))
       )
)

(print (replace '(1 2 7 1 0 1 4) 1 6))

;-------

;------ 9 задание
(defun neql (a b) ; функция обратна функции eql
  (not (eql a b))
)

(defun even (array) ; возвращает подсписок списка array, в котором все элементы-цифры четные
    (cond
        ((null array) nil)
        ((eql 0 (mod (car array) 2)) (cons (car array) (even (cdr array))))
        (t (even (cdr array)))
    )
)

(defun odd (array) ; возвращает подсписок списка array, в котором все элементы-цифры нечетные
	(cond
        ((null array) nil)
        ((neql 0 (mod (car array) 2)) (cons (car array) (odd (cdr array))))
        (t (odd (cdr array)))
    )
)

(defun even_odd (array) (list (odd array) (even array))) ; разделяет список из цифр array на нечетный и четный списки

(print (even_odd '(1 2 3 4 5 6 7 8 9 10)))

;------

;------ 10 задание
(defun pop (array) ; удаляет последний элемент из списка array
	(cond
		((null (cdr array)) nil)
		(t (cons (car array) (pop (cdr array))))
	)
)

(defun del (array count) ; удаляет count последних элементов из списка array
	(cond
		((eql count 1) (pop array))
		(t (del (pop array) (- count 1)))
	)
)

(print (del '(1 2 3 4 5 6 7 8 9 10) 3))

;-----

(defun in (elem array) ; проверяет находится ли elem в списке array
	(cond
		((null array) nil)
		((eql elem (car array)) t)
		(t (in elem (cdr array)))
	)
)

(defun set (array) ; возвращает множество (только уникальные элементы) из списка array
	(cond
		((null array) nil)
		((in (car array) (cdr array)) (set (cdr array)))
		(t (cons (car array) (set (cdr array))))
	)
)

;----- 17 задание
(defun remove (elem array) ; удаляет первое вхождение elem из списка array
	(cond
		((null array) nil)
		((eql elem (car array)) (cdr array))
		(t (cons (car array) (remove elem (cdr array))))
	)
)

(defun adds (elem sets) ; добавляет в каждый список из sets в начало elem
	(cond
		((null sets) nil)
		(t (cons (cons elem (car sets)) (adds elem (cdr sets))))
	)
)

(defun pair (elem array) ; формирует пару значений (значение elem из списка array; список array без этого значения)
  (list elem (remove elem array))
)

(defun pairs (array elems) ; формирует список пар значений (значение из списка elems; список array без этого значения)

  (cond
    ((null elems) nil)
    (t (cons (pair (car elems) array) (pairs array (cdr elems))))
  )
)

(defun info-pair (pair1) ; создает комбинацию или комбинации значений пары
  (cond
    ((null (cdadr pair1)) (list (list (car pair1) (caadr pair1))))
    (t (adds (car pair1) (all-swap (cadr pair1))))
  )
)

(defun info-pairs (set_pairs) ; создает комбинации значений пар
  (cond
    ((null set_pairs) nil)
    (t 
    	(append 
    		(info-pair (car set_pairs))
            (info-pairs (cdr set_pairs))
        )
    )
  )
)

(defun all-swap (set) ; создает все перестановки списка set
  (let ((all_pair (pairs set set)))
    (info-pairs all_pair)
  )
)

(print (all-swap (set '(1 2 3 3 1))))

;-----

;------- 18
(defun is-atoms (array) ; проверяет состоит ли список array только из атомов
	(cond
		((null array) t)
		((atom (car array)) (is-atoms (cdr array)))
		(t nil)
	)
)

(print (is-atoms '(7 6 3 0 3)))
(print (is-atoms '(7 6 3 (0 3))))

;--------

;-------23
(defun in-list (array) ; формирует вложенный список
	(cond
		((null (cdr array)) array)
		(t (list (car array) (in-list (cdr array))))
	)
)

(defun out-list (array) ; раскрывает вложенный список 
	(cond
		((null (cdr array)) array)
		(t (cons (car array) (out-list (cadr array))))
	)
)

(setf a (in-list '(a b c d)))
(print a)
(print (out-list a))

;-------

;------ 34
(defun РАВЕНСТВО-МНОЖЕСТВ (set1 set2)
	(cond
		((and (null set1) (null set2)) t)
		((null set1) nil)
		((null set2) nil)
		((in (car set1) set2) (РАВЕНСТВО-МНОЖЕСТВ (cdr set1) (remove (car set1) set2)))
		(t nil)
	)
)

(print (РАВЕНСТВО-МНОЖЕСТВ '(1 2 3 4) '(4 1 3 2)))
(print (РАВЕНСТВО-МНОЖЕСТВ '(1 2 3 4) '(4 1 3)))

;------

;------ 38
(defun union (set1 set2)
	(cond
		((null set1) set2)
		((null set2) set1)
		((in (car set2) set1) (union set1 (cdr set2)))
		(t (union (cons (car set2) set1) (cdr set2)))
	)
)

(print (union (set '(1 2 3 4 1 2)) (set '(3 4 3 5 10))))

;-----

;----- 42
(defun max2 (a b) ; максимум двух чисел
  (cond 
    ((> a b) a)
    (t b)
  )
)

(defun max-of-subtrees (subtrees curr-max) ; обход списка поддеревьев, поддерживая текущий максимум
  (cond 
    ((null subtrees) curr-max)
    (t (max-of-subtrees (cdr subtrees)
                            (max2 curr-max (max-tree (car subtrees)))))
  )
)

(defun max-tree (tree) ; максимальное значение в дереве
  (cond 
    ((atom tree) tree)                    
    (t (max-of-subtrees (cdr tree) (car tree)))
  )
)

(max-tree '(5 (3 8 2) (7 (2 4 0) 9))) 
(max-tree '(42))                    
(max-tree '(6 (10 34 20) (40 18 5))) 

;-----

;------ 45
(defun РАССТОЯНИЕ (a b)
  (let ((dx (- (get a 'x) (get b 'x)))
        (dy (- (get a 'y) (get b 'y))))
    (sqrt (+ (* dx dx) (* dy dy))))
)

(setf (get 'москва 'x) 0)
(setf (get 'москва 'y) 0)
(setf (get 'питер 'x) 3)
(setf (get 'питер 'y) 4)

(print (РАССТОЯНИЕ 'москва 'питер))

;-------
