;;******************************************************************************** ******************** ;;???????????????***************** header header header header *****************????????????********** ;; ;; assignment 7: where am i?

spring 2008 cs107 ;; by: taj mahetheno ;; ;; (in the spirit of spiting this terrible assignment and language) ;; ;; ;;******************************************************************************** ******************** ;;???????????????***************** directions directions directions ************????????????********** ;; this is actually functional code that i had to write for a terrible assignment in a computer ;; science class at stanford. this program was written in the scheme programming language. ;; to run it: load the file "where-i-am.scm" in your scheme runtime environment such as "kawa" ;; then use the function "where-am-i" with parameters "distances" and "starlocations ;; it is a pretty simple program that takes the distances and star-locations and figures ;; out all possible places where you could be in a two dimensional space with regard to ;; the distances from each of the stars. the list printed out is in order from most likely ;; position to least likely. this is a terrible explination i know but if you actually care ;; you can see the whole assignment at http://www.stanford.edu/class/cs107/handouts/34-assignment-7-where-am-i.pdf ;; ;; ;; ;; ;; to run the program 1) open your scheme environment 2) type " (load "where-i-am.scm") " and hit enter 3) type " (where-am-i distances star-locations) " and hit enter ** note: don't get confused with the actual name of the file **

;; final test list variables (define distances '(2.5 11.65 7.75)) (define star-locations '((0 0) (4 4) (10 0)) )

(define (where-am-i dists points) (map (lambda (star-list) (list (all-guesses dists points) )))) seq) (if (null? seq) '(null

(sort-points( (best-estimate ( define ( string) (apply

apply append star-list))) intersection-points append (map

(lambda (element) (append (list ( )) (create-points seq ) ))))( points-list) lambda ( testpoint)) )))(define ) (append ( append (list testpoint points-list ))(list ) ( define ( points-list) (apply append ( testpoint) ) points-list (floor (/ (length (average-point (carcircle points-list )) ) ( / ( (length points-list#|comment|# #|comment|# points-list)) (list carcircle #|comment|# (average-point (clumped-points rate-points )))) (define (create-points#||#

car element)) (cdr element) define (distance-product point (eval (append '( * ) (map ( testpoint ) ( dist point (remove point points-list)) (rate-points points-list map ( lambda( testpoint ) ( (distance-product testpoint) )) points-list)) clumped-points map (lambda ( testpoint)(cdr (prefix-of-list points-list)2 ))))))(define points-list)(let( (make-pt( / ( caar ( avgpt (length points-list) cadar (avgpt points-list)) ))) ) ) ( append(list (distance-product carcircle #|t|# ))#||#))( define #||# (best-estimate points-list) #|t|# #|comen|# (sort-points( (intersection-points points-list)) circles)( if (null? circles

)'() ( if (null? (cddr circles)) (list (intersect (car circles) (cadr circles))) (let ((carcircle (car circles)))(append (map(lambda (cdrcircle)(intersect carcircle cdrcircle)) (cdr circles)) (create-points (cdr circles)))))))(define (partitioner pivot num-list) (if (null? num-list) '(() ())(let ((split-of-rest (partitioner pivot (cdr num-list))))(if (< (caar num-list) pivot) (list (cons (car num-list) (car

split-of-rest)) (cadr split-of-rest)) (list (car split-of-rest) (cons (car num-list) (car (cdr split-of-rest))))))))(define (sort-points num-list) (if (<= (length num-list) 1) num-list (let ((split (partitioner (caar num-list) (cdr num-list)))) (append (sort-points (car split)) (list (car num-list)) (sort-points (cadr split)))))) (define (avgpt points-list) (if (null? (cdr points-list)) points-list (avgpt (append (cddr points-list) (list( make-pt (+ (x (car points-list)) (x (cadr points-list))) (+ (y (car points-list)) (y (cadr points-list)))))))))

;;******************************************************************************** ******************** ;;???????????????*****************?????????????????????????????*************?????? ??????************** ;; the where-am-i helper functions: ;; ;; the 2-d point type (x and y coordinates) ;; impelemented as a list length 2 ;; ;; the circle type (a radius and a center point) ;; implemented as a list length 2-- first element is the radius and ;; the second is the center point ;; ;; for convenience, i do not insist that you treat these as adt's;; so if you want to use car to get the x coordinate, or build you own ;; circles without going through make-circle that will be ok. ;; ;; point functions: ;; make-pt create a new point ;; x get the x coordinate of a point ;; y get the y coordinate of a point ;; dist return the distance between two points ;; ;; circle functions ;; make-circle create a new circle ;; radius get the radius of a circle ;; center get the center of a circle ;; intersect given two circles, returns a list of the points ;; of intersection for those circles. ;; for the purposes of this program i have ;; bastardized the definition of 'intersect' a little ;; to give better results when the measurements are ;; inexact. don't worry about that, just use the points ;; returned. someone who is interested in math or geometry ;; might be interested to see how i compute the intersection. (define (make-pt x y) (list x y)) (define (x pt) (car pt)) (define (y pt) (cadr pt)) (define (dist pt1 pt2) (let ((dx (- (x pt1) (x pt2))) (dy (- (y pt1) (y pt2)))) (sqrt (+ (* dx dx) (* dy dy))))) ;; ;; 2d vector operations - used by the intersection function ;; vectors are a lot like points. you won't need these. ;;

(define (add v1 v2) (list (+ (car v1) (car v2)) (+ (cadr v1) (cadr v2)))) (define (sub v1 v2) (list (- (car v1) (car v2)) (- (cadr v1) (cadr v2)))) (define (len v) (sqrt (+ (* (car v) (car v)) (* (cadr v) (cadr v))))) (define (scale v factor) (list (* (car v) factor) (* (cadr v) factor))) (define (normalize v) (scale (list (- (cadr v)) (car v)) (/ (len v)))) (define (make-circle radius center) (list radius center)) (define (radius circle) (car circle)) (define (center circle) (cadr circle)) ;; ;; ;; ;; ;; ;; function: intersect ------------------return a list of the points of intersection of the two circles. the circles may not have the same center point

(define (intersect circle1 circle2) (if (equal? (center circle1) (center circle2)) (error "intersect cannont handle circles with the same center point.") (let* ((c1 (center circle1)) (r1 (radius circle1)) (c2 (center circle2)) (r2 (radius circle2)) (d (dist c1 c2))) ;; first check to see if the circles are too far apart to intersect, ;; or if one circle is within another. (if (or (> d (+ r1 r2)) (> r1 (+ d r2)) (> r2 (+ d r1))) ;; if there is no real intersection, use the closest tangent points on each ;; circle. this is the bastardization above. (list (add c1 (scale (sub c2 c1) (/ r1 d))) ;; c1-> towards c2 (add c2 (scale (sub c1 c2) (/ r2 d)))) ;; c2-> towards c1 ;;otherwise the circles intersect normally, and i did some hairy ;;geometry to show that the following computes the two points ;;of intersection. (let* ((r12 (* r1 r1)) (r22 (* r2 r2))

(d2 (* d d)) (d1 (/ (+ r12 (- r22) d2) 2 d)) (h (sqrt (- r12 (* d1 d1)))) (towards (scale (sub c2 c1) (/ d1 d))) ;;vector c1->c2 (perp (scale (normalize towards) h))) (list (add c1 (add towards perp)) (add c1 (add towards (scale perp -1))))))))) ;; ;; ;; ;; ;; ;; function: prefix-of-list -----------------------accepts the incoming list and returns one with the same first k elements and nothing more.

(define (prefix-of-list ls k) (if (or (zero? k) (null? ls)) '() (cons (car ls) (prefix-of-list (cdr ls) (- k 1))))) ;; ;; ;; ;; ;; ;; ;; ;; ;; ;; function: partition ------------------takes a pivot and a list and produces a pair two lists. the first of the two lists contains all of those element less than the pivot, and the second contains everything else. notice that the first list pair every produced is (() ()), and as the recursion unwinds exactly one of the two lists gets a new element cons'ed to the front of it.

(define (partition pivot num-list) (if (null? num-list) '(() ()) (let ((split-of-rest (partition pivot (cdr num-list)))) (if (< (car num-list) pivot) (list (cons (car num-list) (car split-of-rest)) (cadr split-of-rest)) (list (car split-of-rest) (cons (car num-list) (car (cdr split-ofrest)))))))) ;; ;; ;; ;; ;; ;; ;; ;; ;; ;; ;; function: quicksort ------------------implements the quicksort algorithm to sort lists of numbers from high to low. if a list is of length 0 or 1, then it is trivially sorted. otherwise, we partition to cdr of the list around the car to generate two lists: those in the cdr that are smaller than the car, and those in the cdr that are greater than or equal to the car. we then recursively quicksort the two lists, and then splice everything together in the proper order.

(define (quicksort num-list) (if (<= (length num-list) 1) num-list (let ((split (partition (car num-list) (cdr num-list)))) (append (quicksort (car split)) (list (car num-list)) (quicksort (cadr split)))))) ;;

;; ;; ;; ;; ;; ;;

function: remove ---------------generates a copy of the specified list, except that all instances that match the specified elem in the equal? sense are excluded.

(define (remove elem ls) (cond ((null? ls) '()) ((equal? (car ls) elem) (remove elem (cdr ls))) (else (cons (car ls) (remove elem (cdr ls)))))) ;; ;; ;; ;; ;; ;; ;; function: all-guesses --------------------given a list of distances and a list of stars, return a list of all the possible guesses. a single guess is a list of circles which pairs each distance with one of the stars.

(define (all-guesses distances stars) (if (or (null? distances) (null? stars)) '(()) (apply append (map (lambda (star) (map (lambda (pair) (cons (list (car distances) star) pair)) (all-guesses (cdr distances) (remove star stars)) ) ) stars)))) (define *distances-1* '(2.65 5.55 5.25)) (define *stars-1* '((0 0) (4 6) (10 0) (7 4) (12 5))) (define *distances-2* '(2.5 11.65 7.75)) (define *stars-2* '((0 0) (4 4) (10 0)))