project-euler/p91.lisp

33 lines
975 B
Common Lisp

(defun dot (a b)
"Returns the dot product of vectors A and B"
(reduce #'+ (mapcar #'* a b)))
(defun right-triangle-p (o p q)
"Returns non-NIL if the triangle made by points O, P, and Q (integer coordinates) is a right triangle"
(loop with op = (mapcar #'- o p)
with pq = (mapcar #'- p q)
with qo = (mapcar #'- q o)
repeat 3
do (when (= 0 (dot op pq))
(return t))
(rotatef op pq qo)))
(defun right-triangles-with-integer-coordinates (&optional (max 50))
(let ((count 0)
(mirrored (make-hash-table :test 'equal))
(o (list 0 0)))
(loop for x1 from 0 upto max do
(loop for y1 from 0 upto max do
(loop for x2 from 0 upto max do
(loop for y2 from 0 upto max do
(let ((p (list x1 y1))
(q (list x2 y2)))
(when (and (not (equal p q))
(not (equal o p))
(not (equal o q))
(not (gethash (append p q) mirrored))
(right-triangle-p o p q))
(setf (gethash (append q p) mirrored) t)
(incf count)))))))
count))