From 3ccd5542ea7bad675d25e269d844e8ee17c1ae43 Mon Sep 17 00:00:00 2001 From: Lee Spector Date: Wed, 8 Nov 2023 19:09:43 -0500 Subject: [PATCH] Separate plushy pre-processing from plushy to push translation --- src/propeller/genome.cljc | 80 ++++++++++++++++++++------------------- 1 file changed, 41 insertions(+), 39 deletions(-) diff --git a/src/propeller/genome.cljc b/src/propeller/genome.cljc index afe1dc1..14d1b28 100755 --- a/src/propeller/genome.cljc +++ b/src/propeller/genome.cljc @@ -9,45 +9,47 @@ They hold the genetic material for an `individual`. In the initial population, w "Creates and returns a new plushy made of random instructions and of a maximum size of max-initial-plushy-size." [instructions max-initial-plushy-size] (repeatedly - (rand-int max-initial-plushy-size) - #(utils/random-instruction instructions))) + (rand-int max-initial-plushy-size) + #(utils/random-instruction instructions))) + +(defn plushy->push-internal + [plushy argmap] + (let [opener? #(and (vector? %) (= (first %) 'open))] ;; [open ] marks opens + (loop [push () ;; iteratively build the Push program from the plushy + plushy (mapcat #(let [n (get instructions/opens %)] + (if (and n + (> n 0)) + [% ['open n]] + [%])) + plushy)] + (if (empty? plushy) ;; maybe we're done? + (if (some opener? push) ;; done with plushy, but unclosed open + (recur push '(close)) ;; recur with one more close + push) ;; otherwise, really done, return push + (let [i (first plushy)] + (if (= i 'close) + (if (some opener? push) ;; process a close when there's an open + (recur (let [post-open (reverse (take-while (comp not opener?) + (reverse push))) + open-index (- (count push) (count post-open) 1) + num-open (second (nth push open-index)) + pre-open (take open-index push)] + (if (= 1 num-open) + (concat pre-open [post-open]) + (concat pre-open [post-open ['open (dec num-open)]]))) + (rest plushy)) + (recur push (rest plushy))) ;; unmatched close, ignore + (recur (concat push [i]) (rest plushy)))))))) ;; anything else (defn plushy->push - "Returns the Push program expressed by the given plushy representation. - - The function takes in a plushy representation as input and converts it into a Push program by iteratively processing - the plushy elements and adding instructions to the push program. - It also handles the case where there are open instructions that need to be closed before the end of the program. - " - ([plushy] (plushy->push plushy {})) + "Returns the Push program expressed by the given plushy representation." + ;; use an empty argmap if none provided + ([plushy] + (plushy->push plushy {})) + ;; call plushy->push-internal with possibly-preprocessed plushy ([plushy argmap] - (let [plushy (if (or (> (or (:ah-umad (:variation argmap)) 0) 0) ;; must strip :vary and :protect - (> (or (:autoconstructive-crossover (:variation argmap)) 0) 0)) ;; must strip :gene - (filter (complement #{:vary :protect :gene}) plushy) - plushy) - opener? #(and (vector? %) (= (first %) 'open))] ;; [open ] marks opens - (loop [push () ;; iteratively build the Push program from the plushy - plushy (mapcat #(let [n (get instructions/opens %)] - (if (and n - (> n 0)) - [% ['open n]] - [%])) - plushy)] - (if (empty? plushy) ;; maybe we're done? - (if (some opener? push) ;; done with plushy, but unclosed open - (recur push '(close)) ;; recur with one more close - push) ;; otherwise, really done, return push - (let [i (first plushy)] - (if (= i 'close) - (if (some opener? push) ;; process a close when there's an open - (recur (let [post-open (reverse (take-while (comp not opener?) - (reverse push))) - open-index (- (count push) (count post-open) 1) - num-open (second (nth push open-index)) - pre-open (take open-index push)] - (if (= 1 num-open) - (concat pre-open [post-open]) - (concat pre-open [post-open ['open (dec num-open)]]))) - (rest plushy)) - (recur push (rest plushy))) ;; unmatched close, ignore - (recur (concat push [i]) (rest plushy))))))))) ;; anything else + (plushy->push-internal (if (or (> (or (:ah-umad (:variation argmap)) 0) 0) ;; must strip :vary and :protect + (> (or (:autoconstructive-crossover (:variation argmap)) 0) 0)) ;; must strip :gene + (filter (complement #{:vary :protect :gene}) plushy) + plushy) + argmap))) \ No newline at end of file