From debaffddb210096a01c9965e0ca1611402ce1f05 Mon Sep 17 00:00:00 2001 From: Siraaj Khandkar Date: Mon, 3 Sep 2012 02:21:26 -0400 Subject: [PATCH 01/16] Forest-fire model 001. --- forest-fire/001/.gitignore | 4 + forest-fire/001/Makefile | 18 +++ forest-fire/001/src/forest_fire.ml | 180 +++++++++++++++++++++++++++++ 3 files changed, 202 insertions(+) create mode 100644 forest-fire/001/.gitignore create mode 100644 forest-fire/001/Makefile create mode 100644 forest-fire/001/src/forest_fire.ml diff --git a/forest-fire/001/.gitignore b/forest-fire/001/.gitignore new file mode 100644 index 0000000..a97bb19 --- /dev/null +++ b/forest-fire/001/.gitignore @@ -0,0 +1,4 @@ +bin/* +*.o +*.cmi +*.cmx diff --git a/forest-fire/001/Makefile b/forest-fire/001/Makefile new file mode 100644 index 0000000..7da721b --- /dev/null +++ b/forest-fire/001/Makefile @@ -0,0 +1,18 @@ +COMPILER="ocamlopt" +OBJ_EXT="cmx" + + +compile: + @mkdir -p bin + @ocamlfind $(COMPILER) -linkpkg -package unix \ + -o bin/forest_fire \ + src/forest_fire.ml + + +clean: + @rm -rf bin + @find src \ + -iname '*.o' \ + -or -iname '*.cmi' \ + -or -iname '*.$(OBJ_EXT)' \ + | xargs rm diff --git a/forest-fire/001/src/forest_fire.ml b/forest-fire/001/src/forest_fire.ml new file mode 100644 index 0000000..98dad01 --- /dev/null +++ b/forest-fire/001/src/forest_fire.ml @@ -0,0 +1,180 @@ +open Printf + + +(* ------------------------------------------------------------------------- * + * Constants + * ------------------------------------------------------------------------- *) +let f = 0.01 (* Probability of spontaneous ignition *) +let p = 1.0 (* Probability of spontaneous growth *) + +let default_x = 80 +let default_y = 25 + +let char_empty = ' ' +let char_tree = 'T' +let char_burning = '#' + +let ansi_color_tree = "\027[0;32m" (* Green *) +let ansi_color_burning = "\027[1;31m" (* Red *) +let ansi_color_off = "\027[0m" + +let ansi_code_clear = "\027[2J" (* Clear screen *) +let ansi_code_reset = "\027[1;1H" (* Reset cursor position *) + + +(* ------------------------------------------------------------------------- * + * Types + * ------------------------------------------------------------------------- *) +type cell_state = + | Empty | Tree | Burning + + +type direction = + | N | NE | E | SE | S | SW | W | NW + + +type options = + { size : int * int + } + + +(* ------------------------------------------------------------------------- * + * Utils + * ------------------------------------------------------------------------- *) + +(* Hack to sleep less than 1 sec *) +let minisleep subsec = + ignore (Unix.select [] [] [] subsec) + + +let term_clear () = + print_string ansi_code_clear + + +let term_reset () = + print_string ansi_code_reset + + +let get_opts argv = + let usage = "" + + and x = ref default_x + and y = ref default_y in + + let speclist = Arg.align [ + ("-x", Arg.Set_int x, " X."); + ("-y", Arg.Set_int y, " Y."); + ] in + + Arg.parse speclist (fun _ -> ()) usage; + + { size = !x, !y + } + + +(* ------------------------------------------------------------------------- * + * Core + * ------------------------------------------------------------------------- *) +let directions = + [N; NE; E; SE; S; SW; W; NW] + + +let offset_of_direction = function + (* Direction -> x, y *) + | N -> 0, -1 + | NE -> 1, -1 + | E -> 1, 0 + | SE -> 1, 1 + | S -> 0, 1 + | SW -> -1, 1 + | W -> -1, 0 + | NW -> -1, -1 + + +let offsets = + List.map (offset_of_direction) directions + + +let is_probable = function + | probability when (Random.float 1.0) <= probability -> true + | _ -> false + + +let init_cell_state = function + | () when is_probable p -> Tree + | () -> Empty + + +let init_forest (x, y) = + Array.map (Array.map (init_cell_state)) (Array.make_matrix y x ()) + + +let string_of_state = function + | Empty -> sprintf "%c" char_empty + | Tree -> sprintf "%s%c%s" ansi_color_tree char_tree ansi_color_off + | Burning -> sprintf "%s%c%s" ansi_color_burning char_burning ansi_color_off + + +let new_state = function + | Burning, _ -> Empty + | Tree, 0 when is_probable f -> Burning + | Tree, neighbors_burning when neighbors_burning > 0 -> Burning + | Empty, _ when is_probable p -> Tree + | state, _ -> state + + +let print_forest forest = + Array.iter + ( + fun row -> + Array.iter + ( + fun state -> + print_string (string_of_state state) + ) + row; + print_newline () + ) + forest + + +let is_onside width height (x, y) = + x >= 0 && y >= 0 && x < width && y < height + + +let next_generation forest (width, height) = + Array.mapi + ( + fun iy row -> + Array.mapi + ( + fun ix state -> + let neighbors = List.map (fun (ox, oy) -> ox + ix, oy + iy) offsets in + let neighbors = List.filter (is_onside width height) neighbors in + let neighbor_states = List.map (fun (x, y) -> forest.(y).(x)) neighbors in + let burning_states = List.filter (fun s -> s == Burning) neighbor_states in + new_state (state, (List.length burning_states)) + ) + row + ) + forest + + +let rec burn forest size = + term_reset (); + print_forest forest; + minisleep 0.1; + burn (next_generation forest size) size + + +let main argv = + Random.self_init (); + + let opts = get_opts argv in + let forest = init_forest opts.size in + + term_clear (); + burn forest opts.size + + +let () = main Sys.argv -- 2.20.1 From 8143820a79375d9eba5fb6377a71a0732c6512e6 Mon Sep 17 00:00:00 2001 From: Siraaj Khandkar Date: Mon, 3 Sep 2012 13:32:16 -0400 Subject: [PATCH 02/16] Set probability in CLI options. --- forest-fire/001/src/forest_fire.ml | 48 +++++++++++++++++------------- 1 file changed, 28 insertions(+), 20 deletions(-) diff --git a/forest-fire/001/src/forest_fire.ml b/forest-fire/001/src/forest_fire.ml index 98dad01..fc91c4a 100644 --- a/forest-fire/001/src/forest_fire.ml +++ b/forest-fire/001/src/forest_fire.ml @@ -4,8 +4,8 @@ open Printf (* ------------------------------------------------------------------------- * * Constants * ------------------------------------------------------------------------- *) -let f = 0.01 (* Probability of spontaneous ignition *) -let p = 1.0 (* Probability of spontaneous growth *) +let default_f = 0.01 (* Probability of spontaneous ignition *) +let default_p = 1.0 (* Probability of spontaneous growth *) let default_x = 80 let default_y = 25 @@ -35,6 +35,7 @@ type direction = type options = { size : int * int + ; prob : float * float } @@ -58,17 +59,24 @@ let term_reset () = let get_opts argv = let usage = "" + and f = ref default_f + and p = ref default_p and x = ref default_x and y = ref default_y in - let speclist = Arg.align [ - ("-x", Arg.Set_int x, " X."); - ("-y", Arg.Set_int y, " Y."); - ] in + let speclist = + Arg.align + [ ("-f", Arg.Set_float f, " Probability of spontaneous ignition.") + ; ("-p", Arg.Set_float p, " Probability of spontaneous growth.") + ; ("-x", Arg.Set_int x, " Forest width.") + ; ("-y", Arg.Set_int y, " Forest height.") + ] + in Arg.parse speclist (fun _ -> ()) usage; { size = !x, !y + ; prob = !f, !p } @@ -100,13 +108,13 @@ let is_probable = function | _ -> false -let init_cell_state = function +let init_cell_state (_, p) = function | () when is_probable p -> Tree | () -> Empty -let init_forest (x, y) = - Array.map (Array.map (init_cell_state)) (Array.make_matrix y x ()) +let init_forest (x, y) prob = + Array.map (Array.map (init_cell_state prob)) (Array.make_matrix y x ()) let string_of_state = function @@ -116,11 +124,11 @@ let string_of_state = function let new_state = function - | Burning, _ -> Empty - | Tree, 0 when is_probable f -> Burning - | Tree, neighbors_burning when neighbors_burning > 0 -> Burning - | Empty, _ when is_probable p -> Tree - | state, _ -> state + | Burning, _, _ -> Empty + | Tree, 0, (f, _) when is_probable f -> Burning + | Tree, n_burning, _ when n_burning > 0 -> Burning + | Empty, _, (_, p) when is_probable p -> Tree + | state, _, _ -> state let print_forest forest = @@ -142,7 +150,7 @@ let is_onside width height (x, y) = x >= 0 && y >= 0 && x < width && y < height -let next_generation forest (width, height) = +let next_generation forest (width, height) prob = Array.mapi ( fun iy row -> @@ -153,28 +161,28 @@ let next_generation forest (width, height) = let neighbors = List.filter (is_onside width height) neighbors in let neighbor_states = List.map (fun (x, y) -> forest.(y).(x)) neighbors in let burning_states = List.filter (fun s -> s == Burning) neighbor_states in - new_state (state, (List.length burning_states)) + new_state (state, (List.length burning_states), prob) ) row ) forest -let rec burn forest size = +let rec burn forest size prob = term_reset (); print_forest forest; minisleep 0.1; - burn (next_generation forest size) size + burn (next_generation forest size prob) size prob let main argv = Random.self_init (); let opts = get_opts argv in - let forest = init_forest opts.size in + let forest = init_forest opts.size opts.prob in term_clear (); - burn forest opts.size + burn forest opts.size opts.prob let () = main Sys.argv -- 2.20.1 From 0d55050e503b617f0062495bde9852d6f77e10f3 Mon Sep 17 00:00:00 2001 From: Siraaj Khandkar Date: Mon, 3 Sep 2012 13:44:20 -0400 Subject: [PATCH 03/16] Set generation interval in CLI options. --- forest-fire/001/src/forest_fire.ml | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/forest-fire/001/src/forest_fire.ml b/forest-fire/001/src/forest_fire.ml index fc91c4a..272815f 100644 --- a/forest-fire/001/src/forest_fire.ml +++ b/forest-fire/001/src/forest_fire.ml @@ -7,6 +7,8 @@ open Printf let default_f = 0.01 (* Probability of spontaneous ignition *) let default_p = 1.0 (* Probability of spontaneous growth *) +let default_interval = 0.1 (* Induced interval between generations *) + let default_x = 80 let default_y = 25 @@ -34,8 +36,9 @@ type direction = type options = - { size : int * int - ; prob : float * float + { size : int * int + ; prob : float * float + ; interval : float } @@ -59,6 +62,7 @@ let term_reset () = let get_opts argv = let usage = "" + and interval = ref default_interval and f = ref default_f and p = ref default_p and x = ref default_x @@ -70,13 +74,15 @@ let get_opts argv = ; ("-p", Arg.Set_float p, " Probability of spontaneous growth.") ; ("-x", Arg.Set_int x, " Forest width.") ; ("-y", Arg.Set_int y, " Forest height.") + ; ("-i", Arg.Set_float interval, " Induced interval between generations.") ] in Arg.parse speclist (fun _ -> ()) usage; - { size = !x, !y - ; prob = !f, !p + { size = !x, !y + ; prob = !f, !p + ; interval = !interval } @@ -168,11 +174,11 @@ let next_generation forest (width, height) prob = forest -let rec burn forest size prob = +let rec burn forest size prob interval = term_reset (); print_forest forest; - minisleep 0.1; - burn (next_generation forest size prob) size prob + minisleep interval; + burn (next_generation forest size prob) size prob interval let main argv = @@ -182,7 +188,7 @@ let main argv = let forest = init_forest opts.size opts.prob in term_clear (); - burn forest opts.size opts.prob + burn forest opts.size opts.prob opts.interval let () = main Sys.argv -- 2.20.1 From 8cf59f0f0332f2ee186f4fd8ae5ca00cba00e673 Mon Sep 17 00:00:00 2001 From: Siraaj Khandkar Date: Mon, 3 Sep 2012 14:42:55 -0400 Subject: [PATCH 04/16] Check sleep interval before sleeping. --- forest-fire/001/src/forest_fire.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/forest-fire/001/src/forest_fire.ml b/forest-fire/001/src/forest_fire.ml index 272815f..66285a9 100644 --- a/forest-fire/001/src/forest_fire.ml +++ b/forest-fire/001/src/forest_fire.ml @@ -177,7 +177,7 @@ let next_generation forest (width, height) prob = let rec burn forest size prob interval = term_reset (); print_forest forest; - minisleep interval; + if interval > 0.0 then minisleep interval; burn (next_generation forest size prob) size prob interval -- 2.20.1 From 86e687a7e94874ace3b0e4be3e87e1f99a725215 Mon Sep 17 00:00:00 2001 From: Siraaj Khandkar Date: Mon, 3 Sep 2012 14:48:52 -0400 Subject: [PATCH 05/16] Light refactoring. --- forest-fire/001/src/forest_fire.ml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/forest-fire/001/src/forest_fire.ml b/forest-fire/001/src/forest_fire.ml index 66285a9..3cee973 100644 --- a/forest-fire/001/src/forest_fire.ml +++ b/forest-fire/001/src/forest_fire.ml @@ -138,6 +138,8 @@ let new_state = function let print_forest forest = + term_reset (); + Array.iter ( fun row -> @@ -175,10 +177,12 @@ let next_generation forest (width, height) prob = let rec burn forest size prob interval = - term_reset (); print_forest forest; + if interval > 0.0 then minisleep interval; - burn (next_generation forest size prob) size prob interval + + let next_forest = next_generation forest size prob in + burn next_forest size prob interval let main argv = @@ -188,6 +192,7 @@ let main argv = let forest = init_forest opts.size opts.prob in term_clear (); + burn forest opts.size opts.prob opts.interval -- 2.20.1 From 1361b30d16ae9c8b11b7f5132d2277d927e89b61 Mon Sep 17 00:00:00 2001 From: Siraaj Khandkar Date: Mon, 3 Sep 2012 17:31:08 -0400 Subject: [PATCH 06/16] Right... THAT's how you pass a curried infix. --- forest-fire/001/src/forest_fire.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/forest-fire/001/src/forest_fire.ml b/forest-fire/001/src/forest_fire.ml index 3cee973..bd2ed19 100644 --- a/forest-fire/001/src/forest_fire.ml +++ b/forest-fire/001/src/forest_fire.ml @@ -168,7 +168,7 @@ let next_generation forest (width, height) prob = let neighbors = List.map (fun (ox, oy) -> ox + ix, oy + iy) offsets in let neighbors = List.filter (is_onside width height) neighbors in let neighbor_states = List.map (fun (x, y) -> forest.(y).(x)) neighbors in - let burning_states = List.filter (fun s -> s == Burning) neighbor_states in + let burning_states = List.filter ((==) Burning) neighbor_states in new_state (state, (List.length burning_states), prob) ) row -- 2.20.1 From 18e7ccf43d5295b594c0b6fe38be58a2116c1ba7 Mon Sep 17 00:00:00 2001 From: Siraaj Khandkar Date: Mon, 3 Sep 2012 17:35:16 -0400 Subject: [PATCH 07/16] Fixed wrong quote type. --- forest-fire/001/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/forest-fire/001/Makefile b/forest-fire/001/Makefile index 7da721b..b97d95d 100644 --- a/forest-fire/001/Makefile +++ b/forest-fire/001/Makefile @@ -14,5 +14,5 @@ clean: @find src \ -iname '*.o' \ -or -iname '*.cmi' \ - -or -iname '*.$(OBJ_EXT)' \ + -or -iname "*.$(OBJ_EXT)" \ | xargs rm -- 2.20.1 From 71087648a2731c7e1261bd75dc2c83e12de7ba05 Mon Sep 17 00:00:00 2001 From: Siraaj Khandkar Date: Fri, 17 May 2013 01:04:17 -0300 Subject: [PATCH 08/16] Re-formated summary as a table --- life/README.md | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/life/README.md b/life/README.md index efd3360..df7fcd5 100644 --- a/life/README.md +++ b/life/README.md @@ -13,21 +13,14 @@ Each of the implementations (living in sequentially numbered directories) shall Summary ------- -* __ID:__ 001, - __Language:__ Erlang, - __Approach:__ Board as 1D list. Cells as [gen_server] processes -* __ID:__ 002, - __Language:__ OCaml, - __Approach:__ Board as matrix via functional arrays (sort-of...) -* __ID:__ 003, - __Language:__ Erlang, - __Approach:__ Board as matrix via [array()] -* __ID:__ 004, - __Language:__ AWK, - __Approach:__ Board as 1D string. Ghosts beyond boundaries -* __ID:__ 005, - __Language:__ AWK, - __Approach:__ Board as simulated 3D array + +| ID | Language | Approach | +|-----|----------|----------| +| 001 | Erlang | Board as 1D list. Cells as [gen_server] processes | +| 002 | OCaml | Board as matrix via functional arrays (sort-of...) | +| 003 | Erlang | Board as matrix via [array()] | +| 004 | AWK | Board as 1D string. Ghosts beyond boundaries | +| 005 | AWK | Board as simulated 3D array | [array()]: http://www.erlang.org/doc/man/array.html "Which is not actually an array, but an integer-keyed tree." -- 2.20.1 From 66ca47c0043ceefe68c77c5e3b0bd127389a6ad0 Mon Sep 17 00:00:00 2001 From: Siraaj Khandkar Date: Thu, 6 Sep 2012 01:01:06 -0400 Subject: [PATCH 09/16] Added info about Wireworld. --- wireworld/README.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 wireworld/README.md diff --git a/wireworld/README.md b/wireworld/README.md new file mode 100644 index 0000000..e137b96 --- /dev/null +++ b/wireworld/README.md @@ -0,0 +1,22 @@ +[Wireworld] +=========== + + +States +------ +* Empty +* Electron head +* Electron tail +* Conductor + + +Transitions +----------- +* Empty -> Empty +* Electron head -> Electron tail +* Electron tail -> Conductor +* Conductor -> Electron head if exactly one or two of the neighbouring cells + are electron heads, or remains Conductor otherwise. + + +[Wireworld]: http://en.wikipedia.org/wiki/Wireworld -- 2.20.1 From 223cc9ca1f4cb32eb088f781ac20e90b38bc6fef Mon Sep 17 00:00:00 2001 From: Siraaj Khandkar Date: Wed, 7 Nov 2012 15:28:44 -0500 Subject: [PATCH 10/16] Why not just subtract in AWK? --- life/001/bin/life | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/life/001/bin/life b/life/001/bin/life index 993ca12..fdcf765 100755 --- a/life/001/bin/life +++ b/life/001/bin/life @@ -1,7 +1,7 @@ #! /bin/sh -Y=`expr \`stty size | awk '{print $1}'\` - 3` +Y=`stty size | awk '{print $1 - 3}'` # Reserve 3 charcters for status bar X=`stty size | awk '{print $2}'` NUM_BEAM_PROCESSES=31 -- 2.20.1 From 48db3947dde7fbb04317a98f338bd7846e931505 Mon Sep 17 00:00:00 2001 From: Siraaj Khandkar Date: Sun, 16 Jun 2013 18:27:48 -0400 Subject: [PATCH 11/16] Added some info on Langton's ant. --- langtons-ant/README.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 langtons-ant/README.md diff --git a/langtons-ant/README.md b/langtons-ant/README.md new file mode 100644 index 0000000..c61b443 --- /dev/null +++ b/langtons-ant/README.md @@ -0,0 +1,4 @@ +Langton's ant +============= + +http://en.wikipedia.org/wiki/Langton%27s_ant -- 2.20.1 From 6eb733d332e003fad71aeb7dfd1caf157d652bc1 Mon Sep 17 00:00:00 2001 From: Siraaj Khandkar Date: Wed, 25 Sep 2013 12:56:45 -0400 Subject: [PATCH 12/16] Quick description of Polymorphic Life. --- polymorphic-life/README.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 polymorphic-life/README.md diff --git a/polymorphic-life/README.md b/polymorphic-life/README.md new file mode 100644 index 0000000..e4bd7e5 --- /dev/null +++ b/polymorphic-life/README.md @@ -0,0 +1,4 @@ +Polymorphic Life +================ + +Each cell can have different state transition rules. -- 2.20.1 From 91093fb99712757a1ae5abc3ea4c98cae7c0200f Mon Sep 17 00:00:00 2001 From: Siraaj Khandkar Date: Wed, 25 Sep 2013 13:20:39 -0400 Subject: [PATCH 13/16] Added build and clean recipes. --- polymorphic-life/001/Makefile | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 polymorphic-life/001/Makefile diff --git a/polymorphic-life/001/Makefile b/polymorphic-life/001/Makefile new file mode 100644 index 0000000..fa2bbc3 --- /dev/null +++ b/polymorphic-life/001/Makefile @@ -0,0 +1,15 @@ +.PHONY: build clean + +EXE_TYPE := native + +build: + $(eval executable_name := polymorphic_life) + $(eval executable_name_ext := $(executable_name).$(EXE_TYPE)) + @ocamlbuild src/$(executable_name_ext) + @mkdir -p bin/ + @cp _build/src/$(executable_name_ext) bin/$(executable_name) + @rm $(executable_name_ext) + +clean: + @ocamlbuild -clean + @rm -rf bin/ -- 2.20.1 From 8eed0e7634102dce19e378227e45bdd68b9f40d0 Mon Sep 17 00:00:00 2001 From: Siraaj Khandkar Date: Wed, 25 Sep 2013 13:22:10 -0400 Subject: [PATCH 14/16] Ignore _build and bin directories. --- polymorphic-life/001/.gitignore | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 polymorphic-life/001/.gitignore diff --git a/polymorphic-life/001/.gitignore b/polymorphic-life/001/.gitignore new file mode 100644 index 0000000..02cd8d8 --- /dev/null +++ b/polymorphic-life/001/.gitignore @@ -0,0 +1,2 @@ +_build/ +bin/ -- 2.20.1 From 8c93b722cd62dccd61959609c96ce57e53dbe3e3 Mon Sep 17 00:00:00 2001 From: Siraaj Khandkar Date: Wed, 25 Sep 2013 13:28:17 -0400 Subject: [PATCH 15/16] Say hi. --- polymorphic-life/001/Makefile | 6 +++++- polymorphic-life/001/src/polymorphic_life.ml | 8 ++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 polymorphic-life/001/src/polymorphic_life.ml diff --git a/polymorphic-life/001/Makefile b/polymorphic-life/001/Makefile index fa2bbc3..40aae7d 100644 --- a/polymorphic-life/001/Makefile +++ b/polymorphic-life/001/Makefile @@ -5,7 +5,11 @@ EXE_TYPE := native build: $(eval executable_name := polymorphic_life) $(eval executable_name_ext := $(executable_name).$(EXE_TYPE)) - @ocamlbuild src/$(executable_name_ext) + @ocamlbuild \ + -use-ocamlfind \ + -package core \ + -tag thread \ + src/$(executable_name_ext) @mkdir -p bin/ @cp _build/src/$(executable_name_ext) bin/$(executable_name) @rm $(executable_name_ext) diff --git a/polymorphic-life/001/src/polymorphic_life.ml b/polymorphic-life/001/src/polymorphic_life.ml new file mode 100644 index 0000000..e3c233d --- /dev/null +++ b/polymorphic-life/001/src/polymorphic_life.ml @@ -0,0 +1,8 @@ +open Core.Std + + +let main () = + printf "Hi!\n" + + +let () = main () -- 2.20.1 From 4d49c95e96b6a688ecbc54bea64b810c9611b400 Mon Sep 17 00:00:00 2001 From: Siraaj Khandkar Date: Wed, 25 Sep 2013 14:58:28 -0400 Subject: [PATCH 16/16] Implement a generic matrix abstraction. --- polymorphic-life/001/src/polymorphic_life.ml | 51 +++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/polymorphic-life/001/src/polymorphic_life.ml b/polymorphic-life/001/src/polymorphic_life.ml index e3c233d..a667bc4 100644 --- a/polymorphic-life/001/src/polymorphic_life.ml +++ b/polymorphic-life/001/src/polymorphic_life.ml @@ -1,8 +1,57 @@ open Core.Std +module type MATRIX = sig + type 'a t + + val create : rows:int -> cols:int -> data:'a -> 'a t + + val get : 'a t -> row:int -> col:int -> 'a + + val set : 'a t -> row:int -> col:int -> data:'a -> unit + + val map : 'a t -> f:(row:int -> col:int -> data:'a -> 'b) -> 'b t + + val iter : 'a t -> f:(row:int -> col:int -> data:'a -> unit) -> unit +end + +module Matrix : MATRIX = struct + type 'a t = 'a array array + + let create ~rows ~cols ~data = + Array.make_matrix ~dimx:rows ~dimy:cols data + + let iter t ~f = + Array.iteri t ~f:( + fun row cols -> + Array.iteri cols ~f:( + fun col data -> + f ~row ~col ~data + ) + ) + + let map t ~f = + Array.mapi t ~f:( + fun row cols -> + Array.mapi cols ~f:( + fun col data -> + f ~row ~col ~data + ) + ) + + let get t ~row ~col = + t.(row).(col) + + let set t ~row ~col ~data = + t.(row).(col) <- data +end + + let main () = - printf "Hi!\n" + let pool = Matrix.create ~rows:5 ~cols:5 ~data:() in + Matrix.iter pool ~f:( + fun ~row ~col ~data:() -> printf "R: %d, K: %d\n" row col + ) let () = main () -- 2.20.1