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 | ||
11 | val set : 'a t -> row:int -> col:int -> data:'a -> unit | |
12 | ||
13 | val map : 'a t -> f:(row:int -> col:int -> data:'a -> 'b) -> 'b t | |
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 SK |
42 | let map t ~f = |
43 | Array.mapi t ~f:( | |
44 | fun row cols -> | |
45 | Array.mapi cols ~f:( | |
46 | fun col data -> | |
47 | f ~row ~col ~data | |
48 | ) | |
49 | ) | |
50 | ||
51 | let get t ~row ~col = | |
52 | t.(row).(col) | |
53 | ||
54 | let set t ~row ~col ~data = | |
55 | t.(row).(col) <- data | |
56 | end | |
57 | ||
58 | ||
da8f1674 SK |
59 | module type CELL = sig |
60 | type t | |
61 | ||
0ce0e798 SK |
62 | val init : unit -> t |
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 | ||
5c37daed SK |
88 | let init () = |
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 SK |
106 | Random.self_init (); |
107 | let init ~row:_ ~col:_ ~data = Conway.init data in | |
108 | let grid = Matrix.create ~rows ~cols ~data:() |> Matrix.map ~f:init in | |
109 | Matrix.print grid ~to_string:Conway.to_string | |
8c93b722 SK |
110 | |
111 | ||
7d89c037 SK |
112 | let spec = |
113 | let summary = "Polymorphic Cellular Automata" in | |
114 | let spec = | |
115 | let open Command.Spec in | |
116 | empty | |
117 | +> flag "-rows" (optional_with_default 5 int) ~doc:"Height" | |
118 | +> flag "-cols" (optional_with_default 5 int) ~doc:"Width" | |
119 | in | |
120 | Command.basic ~summary spec main | |
121 | ||
122 | ||
123 | let () = Command.run spec |