(defparameter *points* ()) ;;; This variable defines which points are on the same line. It's ;;; assumed that points on the same line are connected. (defparameter *lines* ()) (defmacro defline (&rest points) `(progn (setf *points* (union ',points *points*)) (push ',points *lines*))) (defline p0 p1) (defline p0 p2 p4 p6) (defline p0 p3 p7 p9) (defline p0 p5 p8 p10) (defline p1 p2 p3 p5) (defline p1 p4 p7 p8) (defline p1 p6 p9 p10) (defun on-a-line-p (&rest points) (find-if (lambda (line) (subsetp points line)) *lines*)) (defun triangle-p (x y z) ;; This detects identical points too. (and (on-a-line-p x y) (on-a-line-p y z) (on-a-line-p z x) (not (on-a-line-p x y z)))) ;;; Make it unnecessarily generalized and longer. (defmacro do-combinations (((&rest vars) list) &body body) (if (endp vars) `(progn ,@body) (let ((tail (gensym))) `(loop for ,tail on ,list for ,(first vars) in ,list do (do-combinations (,(rest vars) (rest ,tail)) ,@body))))) (defun triangles (&optional (points *points*)) (let ((triangles ())) (do-combinations ((x y z) points) (when (triangle-p x y z) (push (list x y z) triangles))) triangles)) (print (length (triangles)))