about summary refs log tree commit diff stats
path: root/js/games/nluqo.github.io/~bh/61a-pages/Lib/tri.l
diff options
context:
space:
mode:
Diffstat (limited to 'js/games/nluqo.github.io/~bh/61a-pages/Lib/tri.l')
-rw-r--r--js/games/nluqo.github.io/~bh/61a-pages/Lib/tri.l94
1 files changed, 94 insertions, 0 deletions
diff --git a/js/games/nluqo.github.io/~bh/61a-pages/Lib/tri.l b/js/games/nluqo.github.io/~bh/61a-pages/Lib/tri.l
new file mode 100644
index 0000000..90e3918
--- /dev/null
+++ b/js/games/nluqo.github.io/~bh/61a-pages/Lib/tri.l
@@ -0,0 +1,94 @@
+;; Program to solve triangles given partial information.
+
+;; Form of invocation is (triangle side1 side2 side3 angle1 angle2 angle3)
+;;   where each argument is zero if the corresponding side or angle is
+;;   unknown.  Angles are entered in degrees (but converted internally
+;;   to radians).  Angle1 is opposite side1, etc.  The program must be
+;;   given at least three knowns, at least one of which must be a side.
+
+;; First, here are some useful definitions from trig class:
+
+(define pi 3.14159)
+
+(define (square x) (* x x))
+
+(define (degrees rad) (* 180 (/ rad pi)))
+
+(define (radians deg) (* pi (/ deg 180)))
+
+(define (arcsin a) (atan a (sqrt (- 1 (square a)))))
+
+(define (arccos a) (atan (sqrt (- 1 (square a))) a))
+
+;; This is the top-level procedure
+
+(define (triangle a b c alpha beta gamma)
+
+  (define (triangle-rad a b c alpha beta gamma)
+
+;; The strategy is to keep increasing the number of sides we know, and at
+;; the end to make sure we know the angles too.  Here are some local
+;; procedures to count how many sides we know.  They are predicates that
+;; return true if we know at least so many sides (or angles sometimes).
+
+    (define (havethreesides) (not (or (= a 0) (= b 0) (= c 0))))
+
+    (define (havetwo a b c)
+      (cond ((= a 0) (not (or (= b 0) (= c 0))))
+	    (else (not (and (= b 0) (= c 0))))))
+    (define (havetwosides) (havetwo a b c))
+    (define (havetwoangles) (havetwo alpha beta gamma))
+
+    (define (haveone a b c)
+      (not (and (= a 0) (= b 0) (= c 0))))
+    (define (haveoneside) (haveone a b c))
+    (define (haveoneangle) (haveone alpha beta gamma))
+
+;; If we know all three sides we can use the law of cosines to find
+;; any angles that might be missing.
+
+    (define (solvethreesides)
+      (define (lawcosangle side1 side2 hyp)
+      	(arccos (/ (- (+ (square side1) (square side2)) (square hyp))
+	      (* 2 side1 side2))))
+      (define (sidesbad)
+	(define (tri-ineq a b c) (> (+ a b) c))
+	(not (and (tri-ineq a b c) (tri-ineq a c b) (tri-ineq b c a))))
+
+      (cond ((sidesbad) "Your sides fail the triangle inequality.")
+	    ((= alpha 0)
+	     (triangle-rad a b c (lawcosangle b c a) beta gamma))
+	    ((= beta 0)
+	     (triangle-rad a b c alpha (lawcosangle a c b) gamma))
+	    ((= gamma 0)
+	     (triangle-rad a b c alpha beta (lawcosangle a b c)))
+	    (else
+	     (list a b c (degrees alpha) (degrees beta) (degrees gamma)))))
+
+;; [You don't know about the procedure "list" yet, but it lets us return
+;; more than one number in a single result.]
+
+;; We invoke this procedure if we know two sides:
+
+    (define (solvetwosides)
+
+;; It'll make life easier if we rearrange things so that side C is unknown.
+
+      (cond ((not (haveoneangle)) "Must know at least three values.")
+	    ((= a 0) (triangle-rad b c a beta gamma alpha))
+	    ((= b 0) (triangle-rad a c b alpha gamma beta))
+	    (else "YOU FILL IN THE REST!")))
+
+;; This is the executable body of triangle-rad:
+
+    (cond ((havethreesides) (solvethreesides))
+	  ((havetwosides) (solvetwosides))
+	  ((haveoneside) (solveoneside))
+	  (else "Must know at least one side.")))
+
+;; This is the executable body of triangle.
+
+  (cond ((> (+ alpha beta gamma) 180)
+	 "Your angles add up to more than 180.")
+  	(else (triangle-rad a b c
+			    (radians alpha) (radians beta) (radians gamma)))))