#!/usr/bin/sbcl --script

;;; ============================================================
;;;# NAME: Peter Uzuriaga
;;;# ASGT: Activity 08
;;;# ORGN: CSUB - CMPS 3500
;;;# FILE: lab08.lisp
;;;# DATE: 05/11/2026
;;; ============================================================

;;; ============================================================
;; 1. Define sum-list.
;; A recursive function that sums all numbers in a list.
;; Functional programming relies heavily on recursion instead of loops!
;;; ============================================================
(defun sum-list (lst)
  "Recursively return the sum of the integers in lst."
  ;; BASE CASE: If the list is empty (null), the sum is 0.
  (if (null lst)
      0
      ;; RECURSIVE CASE: Add the first element (car) to the sum of the rest (cdr).
      (+ (car lst) (sum-list (cdr lst)))))

;;; ============================================================
;; 2. Define sum-list-tail.
;; Tail-recursive function that has an accumulator which carries running total.
;;; ============================================================
(defun sum-list-tail (lst accu)
  (if (null lst)
      accu
      (sum-list-tail (cdr lst) (+ accu (car lst)))))

;;; ============================================================
;; 3. Define remove-duplicates-rec.
;;; ============================================================
(defun remove-duplicates-rec (lst)
  (cond
    ;;; if
    ((null lst) nil)  
    ;;; elseif
    ((member (car lst) (cdr lst)) (remove-duplicates-rec (cdr lst)))
    ;;; else
    (t (cons (car lst) (remove-duplicates-rec(cdr lst))))))

(defun flatten-list (lst)
  (cond
    ((null lst) nil)
    ((listp (car lst))(append (flatten-list (car lst)) (flatten-list (cdr lst))))
    (t (cons (car lst) (flatten-list (cdr lst))))))

(defun run-hardcoded-tests ()
  (format t "Testing sum-list with '(1 2 3 4): ~a~%"
          (sum-list '(1 2 3 4)))
 
  (format t "Testing sum-list-tail '(1 2 3 4) 0: ~a~%"
          (sum-list-tail '(1 2 3 4) 0))
 
  (format t "Testing remove-duplicates-rec '(a b a c b d a): ~a~%"
          (remove-duplicates-rec '(a b a c b d a))))

;; Example of reading Lisp data exactly as an s-expression from a file
(format t "~%Reading data from sample.txt...~%")
(with-open-file (stream "sample.txt" :direction :input :if-does-not-exist nil)
  (if stream
      (let ((file-data (read stream nil)))
        (format t "Read from file => ~a~%" file-data)
        (format t "Sum of file data => ~a~%" (sum-list file-data)))
      (format t "Could not open sample.txt.~%")))

(defun menu ()
  "Interactive menu for running tests."
  (loop
     (format t "~%---------------------------------------------~%")
     (format t "   CMPS 3500 - Functional Programming Menu~%")
     (format t "   lab08.lisp~%")
     (format t "---------------------------------------------~%")
     (format t "Pick an option:~%")
     (format t "  1. Run built-in tests (hardcoded data)~%")
     (format t "  2. Run tests from a file //Not Implemented//~%")
     (format t "  3. Quit~%")
     (format t "Your choice: ")
     (finish-output)
     (let ((choice (read)))
       (cond
         ((eq choice 1) (run-hardcoded-tests))
         ((eq choice 2) 
          (format t "Enter test file name [test.txt]: ")
          (finish-output)
          (let* ((line (read-line))
                 (filename (if (string= line "") "test.txt" line)))
            (read-and-run-tests filename)))
         ((eq choice 3) 
          (format t "Goodbye!~%")
          (return))
         (t (format t "Invalid choice, please select 1, 2, or 3.~%"))))))


(format t "~%Done.~%")
