Problem 21

(require 'cl)
(require 'calc-ext)
(defvar calc-command-flags nil)

(defun hash-to-alist (hash)
  (let (alist)
    (maphash #'(lambda (key val) (push (cons key val) alist)) hash)
    alist ))

(defun find-factor (num)
  (catch 'found
    (let ((i 2))
      (while (math-lessp (math-sub i 1) (math-floor (math-sqrt num)))
	(if (math-equal (math-mod num i) 0)
	    (throw 'found i)
	  (setq i (math-add i 1))) ))))

(defun factorize (num)
  (if (= num 1) nil
    (let ((p-table (make-hash-table)) p val)
      (while (setq p (find-factor num))
	(setq num (/ num p))
	(if (setq val (gethash p p-table))
	    (puthash p (1+ val) p-table)
	  (puthash p 1 p-table) ))
      (if (setq val (gethash num p-table))
	  (puthash num (1+ val) p-table)
	(puthash num 1 p-table) )
      (hash-to-alist p-table) )))

(defun divisor-sum (num)
  (let ((prime-alist (factorize num)) (rst 1))
    (while prime-alist
      (let* ((pair (car prime-alist)) (p (car pair)) (n (cdr pair)) (sum 0))
	(dotimes (i (1+ n))
	  (setq sum (+ (math-pow p i) sum)) )
	(setq prime-alist (cdr prime-alist))
	(setq rst (* rst sum)) ))
    (- rst num) ))

(defun amicable (num)
  (let ((candidate (divisor-sum num)))
    (if (and (not (eq candidate num)) (eq num (divisor-sum candidate)))
	candidate) ))

(let ((i 1) (tmp 0) (sum 0))
  (while (<= i (string-to-number (car argv)))
    (if (setq tmp (amicable i))
	(setq sum (+ sum tmp)) )
    (setq i (1+ i)))
  (princ (math-format-value sum))
  (princ "\n") )