Compute next generation.
[cellular-automata.git] / life / 002 / src / life.ml
... / ...
CommitLineData
1type direction =
2 N | NE | E | SE | S | SW | W | NW
3
4
5let directions =
6 [N; NE; E; SE; S; SW; W; NW]
7
8
9let (|>) x f = f x
10
11
12let char_dead = ' '
13let char_alive = 'o'
14
15
16let char_of_state = function
17 | 0 -> char_dead
18 | 1 -> char_alive
19 | _ -> assert false
20
21
22let offset = function
23 (* direction -> x, y *)
24 | N -> 0, -1
25 | NE -> 1, -1
26 | E -> 1, 0
27 | SE -> 1, 1
28 | S -> 0, 1
29 | SW -> -1, 1
30 | W -> -1, 0
31 | NW -> -1, -1
32
33
34(* Hack to sleep less than 1 sec *)
35let minisleep subsec =
36 ignore (Unix.select [] [] [] subsec)
37
38
39let init_board x y =
40 Array.map (Array.map (fun _ -> Random.int 2)) (Array.make_matrix y x 0)
41
42
43let print_board board =
44 Array.iter
45 (
46 fun row ->
47 Array.iter
48 (fun state -> print_char (char_of_state state))
49 row;
50 print_newline ()
51 )
52 board
53
54
55let new_state = function
56 | 1, live_neighbors when live_neighbors < 2 -> 0
57 | 1, live_neighbors when live_neighbors < 4 -> 1
58 | 1, live_neighbors when live_neighbors > 3 -> 0
59 | 0, live_neighbors when live_neighbors = 3 -> 1
60 | state, _ -> state
61
62
63let filter_offsides width height neighbors =
64 List.filter
65 (fun (x, y) -> x >= 0 && y >= 0 && x < width && y < height)
66 neighbors
67
68
69let neighbors x y =
70 List.map
71 (
72 fun d ->
73 let off_x, off_y = offset d in
74 (x + off_x), (y + off_y)
75 )
76 directions
77
78
79let new_generation board =
80 let h = Array.length board
81 and w = Array.length board.(0) in
82 Array.mapi
83 (
84 fun y row ->
85 Array.mapi
86 (
87 fun x state->
88 let neighbors = neighbors x y |> filter_offsides w h in
89 let states = List.map (fun (x, y) -> board.(y).(x)) neighbors in
90 let live_neighbors = List.fold_left (+) 0 states in
91 new_state (state, live_neighbors)
92 )
93 row
94 )
95 board
96
97
98let rec life_loop board =
99 print_board board;
100 print_newline ();
101 minisleep 0.1;
102 life_loop (new_generation board)
103
104
105let main argv =
106 let x = int_of_string argv.(1)
107 and y = int_of_string argv.(2)
108 in
109
110 Random.self_init ();
111
112 life_loop (init_board x y)
113
114
115let () = main Sys.argv
This page took 0.027703 seconds and 4 git commands to generate.