1 type State = "Dead" | "Alive";
3 type States = Array<State>;
5 type Board = Array<States>;
7 let state_of_integer = (i : number) : State => {
9 { case 0 : return "Dead"
10 ; case 1 : return "Alive"
14 let state_to_string = (state) : string => {
16 { case "Dead" : return " "
17 ; case "Alive": return "o"
21 let board_new = ({rows, columns} : {rows: number, columns: number}) : Board => {
23 for (let r = 0; r < rows; 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);
33 let board_neighbors = (b : Board, origin : {r: number, k: number}) : States => {
35 let cols = b[0].length;
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}
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 =
46 return r >= 0 && k >= 0 && r < rows && k < cols
48 let locations_within_bounds = locations.filter(is_location_within_bounds);
49 return locations_within_bounds.map(({r, k}) => b[r][k]);
52 let state_is_alive = (s : State) : boolean => {
53 if (s === "Alive") {return true} else if (s === "Dead") {return false}
56 let 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) {
60 } else if (state === "Alive" && neighbors_alive < 4) {
62 } else if (state === "Alive" && neighbors_alive > 3) {
64 } else if (state === "Dead" && neighbors_alive === 3) {
71 let board_next = (b0 : Board) : Board => {
73 for (let r = 0; r < b0.length; 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);
85 let board_print_border = (b : Board) : void => {
86 process.stdout.write("+");
87 for (let k = 0; k < b[0].length; k++) {
88 process.stdout.write("-");
90 process.stdout.write("+");
91 process.stdout.write("\n");
94 let board_print = (b : Board) : void => {
95 board_print_border(b);
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++) {
102 let state_string = state_to_string(state);
103 process.stdout.write(state_string);
105 process.stdout.write("|");
106 process.stdout.write("\n");
108 board_print_border(b);
111 let console_clear = () : void => {
112 process.stdout.write("\033[2J");
115 let console_reset = () : void => {
116 process.stdout.write("\033[1;1H");
119 let board_loop = (b0 : Board) : void => {
122 let b1 = board_next(b0);
123 setTimeout(() => board_loop(b1), 250)
126 let 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});