Commit | Line | Data |
---|---|---|
8c93b722 SK |
1 | open Core.Std |
2 | ||
3 | ||
4d49c95e SK |
4 | module type MATRIX = sig |
5 | type 'a t | |
6 | ||
7 | val create : rows:int -> cols:int -> data:'a -> 'a t | |
8 | ||
9 | val get : 'a t -> row:int -> col:int -> 'a | |
10 | ||
65dbef41 SK |
11 | val map : 'a t -> f:('a -> 'b) -> 'b t |
12 | ||
13 | val mapi : 'a t -> f:(row:int -> col:int -> data:'a -> 'b) -> 'b t | |
4d49c95e SK |
14 | |
15 | val iter : 'a t -> f:(row:int -> col:int -> data:'a -> unit) -> unit | |
0ce0e798 SK |
16 | |
17 | val print : 'a t -> to_string:('a -> string) -> unit | |
4d49c95e SK |
18 | end |
19 | ||
20 | module Matrix : MATRIX = struct | |
21 | type 'a t = 'a array array | |
22 | ||
23 | let create ~rows ~cols ~data = | |
24 | Array.make_matrix ~dimx:rows ~dimy:cols data | |
25 | ||
26 | let iter t ~f = | |
27 | Array.iteri t ~f:( | |
28 | fun row cols -> | |
29 | Array.iteri cols ~f:( | |
30 | fun col data -> | |
31 | f ~row ~col ~data | |
32 | ) | |
33 | ) | |
34 | ||
0ce0e798 SK |
35 | let print t ~to_string = |
36 | Array.iter t ~f:( | |
37 | fun row -> | |
38 | Array.iter row ~f:(fun x -> printf "%s" (to_string x)); | |
39 | print_newline () | |
40 | ) | |
41 | ||
4d49c95e | 42 | let map t ~f = |
65dbef41 SK |
43 | Array.map t ~f:(Array.map ~f:(fun x -> f x)) |
44 | ||
45 | let mapi t ~f = | |
4d49c95e SK |
46 | Array.mapi t ~f:( |
47 | fun row cols -> | |
48 | Array.mapi cols ~f:( | |
49 | fun col data -> | |
50 | f ~row ~col ~data | |
51 | ) | |
52 | ) | |
53 | ||
54 | let get t ~row ~col = | |
55 | t.(row).(col) | |
4d49c95e SK |
56 | end |
57 | ||
58 | ||
da8f1674 SK |
59 | module type CELL = sig |
60 | type t | |
61 | ||
b6599385 | 62 | val create : unit -> t |
0ce0e798 SK |
63 | |
64 | val to_string : t -> string | |
65 | ||
da8f1674 SK |
66 | val state : t -> int |
67 | ||
68 | val react : t -> states:int list -> t | |
69 | end | |
70 | ||
71 | ||
0d6f7833 SK |
72 | module Conway : CELL = struct |
73 | type t = D | A | |
74 | ||
0ce0e798 SK |
75 | let of_int = function |
76 | | 0 -> D | |
77 | | 1 -> A | |
78 | | _ -> assert false | |
79 | ||
80 | let to_int = function | |
0d6f7833 SK |
81 | | D -> 0 |
82 | | A -> 1 | |
83 | ||
0ce0e798 SK |
84 | let to_string = function |
85 | | D -> " " | |
86 | | A -> "o" | |
87 | ||
b6599385 | 88 | let create () = |
5c37daed | 89 | Random.int 2 |> of_int |
0ce0e798 SK |
90 | |
91 | let state = to_int | |
92 | ||
0d6f7833 SK |
93 | let react t ~states = |
94 | let live_neighbors = List.fold_left states ~init:0 ~f:(+) in | |
95 | match t with | |
96 | | A when live_neighbors < 2 -> D | |
97 | | A when live_neighbors < 4 -> A | |
98 | | A when live_neighbors > 3 -> D | |
99 | | D when live_neighbors = 3 -> A | |
b36c0aef SK |
100 | | A -> A |
101 | | D -> D | |
0d6f7833 SK |
102 | end |
103 | ||
104 | ||
7d89c037 | 105 | let main rows cols () = |
0ce0e798 | 106 | Random.self_init (); |
b6599385 | 107 | let grid = Matrix.create ~rows ~cols ~data:() |> Matrix.map ~f:Conway.create in |
0ce0e798 | 108 | Matrix.print grid ~to_string:Conway.to_string |
8c93b722 SK |
109 | |
110 | ||
7d89c037 SK |
111 | let spec = |
112 | let summary = "Polymorphic Cellular Automata" in | |
113 | let spec = | |
114 | let open Command.Spec in | |
115 | empty | |
116 | +> flag "-rows" (optional_with_default 5 int) ~doc:"Height" | |
117 | +> flag "-cols" (optional_with_default 5 int) ~doc:"Width" | |
118 | in | |
119 | Command.basic ~summary spec main | |
120 | ||
121 | ||
122 | let () = Command.run spec |