Heronian triangles: Difference between revisions

Content deleted Content added
add swift
→‎{{header|Racket}}: Much improved code, still generate html, but via scribble/html
Line 1,181:
=={{header|Racket}}==
 
<lang>#lang at-exp racket
(require xml/xml data/order scribble/html)
 
;; Returns the area of a triangle iff the sides a,have bgcd 1, cand it is an
;; integer; #f otherwise
(define (A a b c)
(define s (/ (+ a b c) 2)) ; where s=\frac{a+b+c}{2}.
(sqrt (* s (- s a) (- s b) (- s c)))) ; A = \sqrt{s(s-a)(s-b)(s-c)}
 
;; Returns same as A iff a, b, c and A are integers; #f otherwise
(define (heronian?-area a b c)
(and (integer? a) (integer? b) (integer? c)
(let ((h (A a b c))) (and (integer? h) h))))
 
;; Returns same as heronian?-area, with the additional condition that (gcd a b c) = 1
(define (primitive-heronian?-area a b c)
(and (= 1 (gcd a b c))
(heronian?-arealet ([s (/ (+ a b c) 2)]) ; ** If s=\frac{a+b+c}{2}
(and (integer? s) ; (s must be an integer for the area to b an integer)
(let-values ([[q r] (integer-sqrt/remainder ; (faster than sqrt)
(sqrt (* s (- s a) (- s b) (- s c)))) ; A** Then the area =is \sqrt{s(s-a)(s-b)(s-c)}
(* s (- s a) (- s b) (- s c)))])
(and (zero? r) q)))))) ; (return only integer areas)
 
(define (generate-heronian-triangles max-side)
(for*/list ([c (in-range 1 (add1 max-side))]
((a [b (in-range 1 (add1 max-side)c))] ; b<=c
(b [a (in-range 1 (add1 a(- c b)) (add1 b))] ; ensures a<=b and c<a+b
(c [area (in-range 1value (add1heronian?-area a b c)))]
#:when (< a (+ b c) #:when area)
;; datum-order can sort this for the tables (c is the max side length)
(h (in-value (primitive-heronian?-area a b c)))
(letlist ((harea (A+ a b c))) (andc (integer?list h)a hb c))))
#:when h)
(define rv (vector h (+ a b c) (sort (list a b c) >))) ; datum-order can sort this for the tables
rv))
 
;; Order the triangles by first increasing area, then by increasing perimeter,
;; then by increasing maximum side lengths
(define (tri<?-sort t1 t2triangles)
(sort triangles (λ(t1 t2) (eq? '< (datum-order t1 t2)))))
 
(define triangle->tds (match-lambda [`#(,h ,p ,s) `((td ,(~a s)) (td ,(~a p)) (td ,(~a h)))]))
 
(define (triangles->table ts)
`(table
(tr (th "#") (th "sides") (th "perimiter") (th "area")) "\n"
,@(for/list ((i (in-naturals 1)) (t ts)) `(tr (td ,(~a i)) ,@(triangle->tds t) "\n"))))
 
(define (sorted-triangles->table triangles)
`(table
(triangles->table (sort triangles tri<?)))
(tr (map th '("#" sides perimeter area))) "\n"
(for/list ([i (in-naturals 1)] [triangle (in-list triangles)])
(match-define (list area perimeter max-side sides) triangle)
(tr (thtd "#"i) (thtd (add-between "sides ",")) (thtd "perimiter"perimeter) (thtd "area")) "\n"))))
 
(module+ main
(define ts (generate-heronian-triangles 200))
(define divoutput-outxml
(@div{@p "{number of primitive triangles found with perimeter "@entity{le"} 200 = " ,(~a @(length ts))) "\n"}
`(div
@; Show the first ten ordered triangles in a table of sides, perimeter,
(p "number of primitive triangles found with perimeter "le" 200 = " ,(~a (length ts))) "\n"
;; Show the first ten ordered triangles in a table of sides, perimeter,@; and area.
, @(sorted-triangles->table (take (tri-sort ts tri<?) 10)) "\n"
; @; Show a similar ordered table for those triangles with area = 210
, @(sorted-triangles->table (tri-sort (filter (match-lambdaλ(t) [(vectoreq? 210 _(car _) #t] [_ #f]) ts)) tri<?)ts)))
}))</lang>
(displayln (xexpr->string div-out)))</lang>
 
This program generates HTML, so the output is inline with the page, not in a <code>&lt;pre></code> block.
Line 1,242 ⟶ 1,232:
 
<div><p>number of primitive triangles found with perimeter &le; 200 = 517</p>
<table><tr><th>#</th><th>sides</th><th>perimiterperimeter</th><th>area</th></tr>
<tr><td>1</td><td>(5 4 3),4,5</td><td>12</td><td>6</td>
</tr><tr><td>2</td><td>(6 5 ,5),6</td><td>16</td><td>12</td>
</tr><tr><td>3</td><td>(8 5 ,5),8</td><td>18</td><td>12</td>
</tr><tr><td>4</td><td>(15 13 4),13,15</td><td>32</td><td>24</td>
</tr><tr><td>5</td><td>(13 12 5),12,13</td><td>30</td><td>30</td>
</tr><tr><td>6</td><td>(17 10 9),10,17</td><td>36</td><td>36</td>
</tr><tr><td>7</td><td>(26 25 3),25,26</td><td>54</td><td>36</td>
</tr><tr><td>8</td><td>(20 15 7),15,20</td><td>42</td><td>42</td>
</tr><tr><td>9</td><td>(10,13 ,13 10)</td><td>36</td><td>60</td>
</tr><tr><td>10</td><td>(17 15 8),15,17</td><td>40</td><td>60</td>
</tr></table>
<table><tr><th>#</th><th>sides</th><th>perimiterperimeter</th><th>area</th></tr>
<tr><td>1</td><td>(28 25 17),25,28</td><td>70</td><td>210</td>
</tr><tr><td>2</td><td>(29 21 20),21,29</td><td>70</td><td>210</td>
</tr><tr><td>3</td><td>(37 35 12),35,37</td><td>84</td><td>210</td>
</tr><tr><td>4</td><td>(39 28 17),28,39</td><td>84</td><td>210</td>
</tr><tr><td>5</td><td>(68 65 7),65,68</td><td>140</td><td>210</td>
</tr><tr><td>6</td><td>(149 148 3),148,149</td><td>300</td><td>210</td>
</tr></table></div>