Source

project-euler / Scheme / 102.scm

Full commit
(tcv-require '(geometry io list))

(define x-coord car)
(define y-coord cadr)

;; Determines if the rectangle formed by points 'a' and 'b' encloses point 'c'.

(define rectangle-encloses?
  (lambda (a b c)
    (and (or (< (x-coord a) (x-coord c) (x-coord b)) (> (x-coord a) (x-coord c) (x-coord b)))
         (or (< (y-coord a) (y-coord c) (y-coord b)) (> (y-coord a) (y-coord c) (y-coord b))))))

;; Determines if a line going through 'a' and the origin will intersect a
;; line-segment between 'b' and 'c'.  This indicates that the triangle formed
;; by 'a' 'b' and 'c' contains the origin.

(define intersection-ok?
  (lambda (a b c)
    (let* ((intersect (line-intersect (list a '(0 0)) (list b c))))
      (rectangle-encloses? b c intersect))))

(define contains-origin?
  (lambda (points)
    (let ((p1 (list-ref points 0))
          (p2 (list-ref points 1))
          (p3 (list-ref points 2)))
      (and (intersection-ok? p1 p2 p3)
           (intersection-ok? p2 p1 p3)
           (intersection-ok? p3 p1 p2)))))

(define parse-triangles
  (lambda (path)
    (letrec ((%parse-triangles (lambda (count)
                                 (let ((line (read-line)))
                                   (if (eof-object? line)
                                     count
                                     (let ((points (list-gather
                                                     (map string->number (string-split line #\,)) 2)))
                                       (if (contains-origin? points)
                                         (%parse-triangles (+ 1 count))
                                         (%parse-triangles count))))))))
      ;; Why oh why is this in Windows format?
      (with-input-from-file (list path: path
                                  eol-encoding: 'cr-lf) (lambda () (%parse-triangles 0))))))