From 1120cb42e8a462896176c07a736769d58ca13e1d Mon Sep 17 00:00:00 2001
From: Simon Brooke <simon@journeyman.cc>
Date: Thu, 28 Aug 2014 21:43:36 +0100
Subject: [PATCH] Work on trying to improve performance.

---
 src/mw_engine/core.clj  | 31 +++++++++++++++++++++++++------
 src/mw_engine/utils.clj | 16 ++++++++++------
 2 files changed, 35 insertions(+), 12 deletions(-)

diff --git a/src/mw_engine/core.clj b/src/mw_engine/core.clj
index 771f355..b066fb3 100644
--- a/src/mw_engine/core.clj
+++ b/src/mw_engine/core.clj
@@ -2,7 +2,8 @@
 
 (ns mw-engine.core
   (:use mw-engine.utils)
-  (:require [mw-engine.world :as world])
+  (:require [clojure.core.reducers :as r]
+            [mw-engine.world :as world])
   (:gen-class))
 
 ;; Every rule is a function of two arguments, a cell and a world. If the rule
@@ -79,16 +80,34 @@
    these `:rules`. As a side effect, print the world."
   [state]
   (let [world (transform-world (:world state) (:rules state))]
-    (world/print-world world)
+    ;;(world/print-world world)
     {:world world :rules (:rules state)}))
 
+
 (defn run-world
   "Run this world with these rules for this number of generations.
 
   * `world` a world as discussed above;
   * `init-rules` a sequence of rules as defined above, to be run once to initialise the world;
-  * `rules` a sequence of rules as definied above, to be run iteratively for each generation;
-  * `generations` an (integer) number of generations."
-  [world init-rules rules generations]
+  * `rules` a sequence of rules as defined above, to be run iteratively for each generation;
+  * `generations` an (integer) number of generations.
+
+  Return the final generation of the world."
+  [world init-rules rules generations]  
   (let [state {:world (transform-world world init-rules) :rules rules}]
-    (take generations (iterate transform-world-state state))))
+    (:world 
+      (last 
+        (do-all 
+          (take generations 
+                (iterate transform-world-state state)))))))
+
+(defn run-world2
+  "Doesn't work yet"
+  [world init-rules rules generations]
+  (with-local-vars [r (ref (transform-world world init-rules))]
+    (dotimes [g generations]
+      (dosync
+        (ref-set r (transform-world (deref r) rules))))
+    (deref r)))
+        
+  
diff --git a/src/mw_engine/utils.clj b/src/mw_engine/utils.clj
index 3b73c3d..8c6fee5 100644
--- a/src/mw_engine/utils.clj
+++ b/src/mw_engine/utils.clj
@@ -1,7 +1,9 @@
 ;; Utility functions needed by MicroWorld and, specifically, in the interpretation of MicroWorld rule.
 
 (ns mw-engine.utils
-  (:require [clojure.math.combinatorics :as combo]))
+  (:require 
+    [clojure.core.reducers :as r]
+    [clojure.math.combinatorics :as combo]))
 
 (defn abs
   "Surprisingly, Clojure doesn't seem to have an abs function, or else I've
@@ -34,11 +36,13 @@
   ([world function]
     (map-world world function nil))
   ([world function additional-args]
-    (apply vector ;; vectors are more efficient for scanning, which we do a lot.
-         (for [row world]
-           (apply vector
-                  (map #(apply function (cons world (cons % additional-args)))
-                       row))))))
+    (into [] ;; vectors are more efficient for scanning, which we do a lot.
+           (r/map (fn [row]
+                    (into [] (r/map 
+                             #(apply function 
+                                     (cons world (cons % additional-args)))
+                             row)))
+                  world))))
 
 (defn get-cell
   "Return the cell a x, y in this world, if any.