Implement vanilla GoL in TypeScript
[cellular-automata.git] / life / 006 / life.ts
CommitLineData
e16b8b54
SK
1type State = "Dead" | "Alive";
2
3type States = Array<State>;
4
5type Board = Array<States>;
6
7let state_of_integer = (i : number) : State => {
8 switch (i)
9 { case 0 : return "Dead"
10 ; case 1 : return "Alive"
11 }
12};
13
14let state_to_string = (state) : string => {
15 switch (state)
16 { case "Dead" : return " "
17 ; case "Alive": return "o"
18 }
19};
20
21let board_new = ({rows, columns} : {rows: number, columns: number}) : Board => {
22 let b = [];
23 for (let r = 0; r < rows; r++) {
24 b[r] = [];
25 for (let k = 0; k < columns; k++) {
26 let zero_or_one = Math.round(Math.random());
27 b[r][k] = state_of_integer(zero_or_one);
28 };
29 };
30 return b
31};
32
33let board_neighbors = (b : Board, origin : {r: number, k: number}) : States => {
34 let rows = b.length;
35 let cols = b[0].length;
36 let offsets =
37 [ {r: -1, k: -1}, {r: -1, k: 0}, {r: -1, k: 1}
38 , {r: 0, k: -1}, {r: 0, k: 1}
39 , {r: 1, k: -1}, {r: 1, k: 0}, {r: 1, k: 1}
40 ];
41 let offset_to_location =
42 (offset) => {return {r: origin.r + offset.r, k: origin.k + offset.k}};
43 let locations = offsets.map(offset_to_location);
44 let is_location_within_bounds =
45 ({r, k}) => {
46 return r >= 0 && k >= 0 && r < rows && k < cols
47 };
48 let locations_within_bounds = locations.filter(is_location_within_bounds);
49 return locations_within_bounds.map(({r, k}) => b[r][k]);
50};
51
52let state_is_alive = (s : State) : boolean => {
53 if (s === "Alive") {return true} else if (s === "Dead") {return false}
54};
55
56let state_next = (state : State, neighbor_states : Array<State>) : State => {
57 let neighbors_alive = neighbor_states.filter(state_is_alive).length;
58 if (state === "Alive" && neighbors_alive < 2) {
59 return "Dead"
60 } else if (state === "Alive" && neighbors_alive < 4) {
61 return "Alive"
62 } else if (state === "Alive" && neighbors_alive > 3) {
63 return "Dead"
64 } else if (state === "Dead" && neighbors_alive === 3) {
65 return "Alive"
66 } else {
67 return state
68 }
69}
70
71let board_next = (b0 : Board) : Board => {
72 let b1 = [];
73 for (let r = 0; r < b0.length; r++) {
74 b1[r] = [];
75 for (let k = 0; k < b0[r].length; k++) {
76 let neighbors = board_neighbors(b0, {r: r, k: k});
77 let state_0 = b0[r][k];
78 let state_1 = state_next(state_0, neighbors);
79 b1[r][k] = state_1;
80 }
81 };
82 return b1
83};
84
85let board_print_border = (b : Board) : void => {
86 process.stdout.write("+");
87 for (let k = 0; k < b[0].length; k++) {
88 process.stdout.write("-");
89 };
90 process.stdout.write("+");
91 process.stdout.write("\n");
92};
93
94let board_print = (b : Board) : void => {
95 board_print_border(b);
96 let rows = b.length;
97 let columns = b[0].length;
98 for (let r = 0; r < rows; r++) {
99 process.stdout.write("|");
100 for (let k = 0; k < columns; k++) {
101 let state = b[r][k];
102 let state_string = state_to_string(state);
103 process.stdout.write(state_string);
104 };
105 process.stdout.write("|");
106 process.stdout.write("\n");
107 };
108 board_print_border(b);
109};
110
111let console_clear = () : void => {
112 process.stdout.write("\033[2J");
113}
114
115let console_reset = () : void => {
116 process.stdout.write("\033[1;1H");
117}
118
119let board_loop = (b0 : Board) : void => {
120 console_reset();
121 board_print(b0);
122 let b1 = board_next(b0);
123 setTimeout(() => board_loop(b1), 250)
124};
125
126let main = () : void => {
127 let height = parseInt(process.argv[2])
128 let width = parseInt(process.argv[3])
129 let b = board_new({rows: height - 3, columns: width - 2});
130 console_clear();
131 board_loop(b);
132};
133
134main();
This page took 0.027237 seconds and 4 git commands to generate.