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