;5.
;a) Write twice the n-th element of a linear list. Example: for (10 20 30 40 50) and n=3 will produce (10 20 30 30 40 50).

;duplicate-nth-element(l1l2...ln, n) =
;  empty list if l1l2...ln is empty
;  l1 + l1l2...ln if n = 1
;  l1 + duplicate-nth-element(l2...ln, n) otherwise

(defun duplicate-nth-element (lst n)
    (cond   
        ((null lst) nil)
        ((< n 1 ) lst )
        ((= n 1) (cons (car lst) lst))
        (t (cons (car lst) (duplicate-nth-element (cdr lst) (- n 1))))
    )
)

(print (duplicate-nth-element '(10 20 30 40 50) 3))
(print (duplicate-nth-element '(10 20 30 40 50) 30))
(print (duplicate-nth-element '(10 20 30 40 50) -1))


;b) Write a function to return an association list with the two lists given as parameters.
; Example: (A B C) (X Y Z) --> ((A.X) (B.Y) (C.Z)).

;create-association-list(l1l2...ln, m1m2...mn) =
;  empty list if l1l2...ln and m1m2...mn are empty
;  (l1, m1) + create-association-list(l2...ln, m2...mn) otherwise
; (l1, nil) + create-association-list(l2...ln, m1m2...mn) if m1m2...mn is empty
; (nil, m1) + create-association-list(l1l2...ln, m2...mn) if l1l2...ln is empty
 (defun create-association-list (list1 list2)
  (if (and (null list1) (null list2))
      '()
      (let ((key (car list1))
            (value (car list2)))
        (cons (cons key value)
              (create-association-list (cdr list1) (cdr list2))))))

(print (create-association-list '(A B C) '(X Y Z)))
(print (create-association-list '(A B) '(X Y Z)))
(print (create-association-list '(A B C) '(X Y)))

;c) Write a function to determine the number of all sublists of a given list, on any level. A sublist is either the list itself, or any element that is a list, at any level. Example:
 ;(1 2 (3 (4 5) (6 7)) 8 (9 10)) => 5 lists:
;(list itself, (3 ...), (4 5), (6 7), (9 10)).

;count-sublists-helper(l1l2...ln) =
;  0 if l1l2...ln is empty
;  1 + count-sublists-helper(l2...ln) + count-sublists-helper(l1) if l1 is a list
;  count-sublists-helper(l2...ln) otherwise
(defun count-sublists-helper (lst)
  (if (null lst)
      0
      (let ((head (car lst))
            (tail (cdr lst)))
        (if (listp head)
            (+ 1 (count-sublists-helper head) (count-sublists-helper tail))
            (count-sublists-helper tail)))))

;count-sublists(lst) =
;  0 if lst is empty
;  1 + count-sublists-helper(lst) otherwise
(defun count-sublists (lst)
    (if (listp lst)
    (+ 1 (count-sublists-helper lst))
    0))


(print (count-sublists '(1 2 (3 (4 5) (6 7)) 8 (9 10))))
(print (count-sublists '(1 2 (3 (4 5) (6 7)) 8 (9 10) (11))))

;d) Write a function to return the number of all numerical atoms in a list at superficial level.

;count-numerical-atoms(l1l2...ln) =
;  0 if l1l2...ln is empty
;  1 + count-numerical-atoms(l2...ln) if l1 is a number
;  count-numerical-atoms(l2...ln) otherwise
(defun count-numerical-atoms (lst)
  (if (null lst)
      0
      (let ((head (car lst))
            (tail (cdr lst)))
        (if (numberp head)
            (+ 1 (count-numerical-atoms tail))
            (count-numerical-atoms tail)))))

(print(count-numerical-atoms '(1 2 (3 (4 5) (6 7)) 8 (9 10))))

(exit)

