Fri, 07 Jul 2006
Functional Triangles.
Our friend Mark Greenaway has been playing around with Ocaml. He's written a program that draws n-sided polygons (for odd n) and then draws lines between the midpoint of each line segment and the opposite vertex to show that all of those lines will coincide at a point which is the middle of the polygon.
Mark's
solution
to this problem is pretty typical of a programmer who comes to Ocaml from
imperative languages.
Typically it uses a bunch of for loops when better, more functional techniques
exist
.
Here's my solution to the problem:
(* To compile this: ocamlc graphics.cma triangles2.ml -o triangles2 *)
open Graphics
let pi = 3.1415926535897932384626433832795
let window_width = 640
let window_height = 480
let gen_points count =
let cx = window_width / 2 in
let cy = window_height / 2 in
let ary = Array.create count 0 in
let radius = 0.9 *. float_of_int cy in
let delta_angle = 2.0 *. pi /. (float_of_int count) in
Array.mapi (fun i x ->
( cx + truncate (radius *. sin (float_of_int i *. delta_angle)),
cy + truncate (radius *. cos (float_of_int i *. delta_angle))
)) ary
let gen_outer_lines points =
set_color black ;
let (x, y) = points.(Array.length points - 1) in
moveto x y ;
Array.iter (fun (x, y) -> lineto x y) points
let gen_center_lines points =
set_color red ;
let do_line sx sy ex ey =
moveto sx sy ;
lineto ex ey
in
let len = Array.length points in
let mid = len / 2 in
Array.iteri (fun i (sx, sy) ->
let (first, second) = ((i + mid) mod len, (i + mid + 1) mod len) in
let (ex1, ey1) = points.(first) in
let (ex2, ey2) = points.(second) in
do_line sx sy ((ex1 + ex2) / 2) ((ey1 + ey2) / 2)
) points
let _ =
let points = gen_points 5 in
open_graph " 640x480" ;
gen_outer_lines points ;
gen_center_lines points ;
set_color blue ;
Array.iter (fun (x, y) -> fill_circle x y 10) points ;
ignore (read_line ())
There's a few algorithmic tweaks here and there but the big difference is the complete lack of for loops.
Posted at: 00:09 | Category: CodeHacking/Ocaml | Permalink