Refactor instructions
This commit is contained in:
parent
af033c1b0e
commit
bb5f74823c
@ -1,5 +1,6 @@
|
|||||||
(ns propeller.core
|
(ns propeller.core
|
||||||
(:gen-class)
|
(:gen-class)
|
||||||
|
(:require [propeller.push.instructions boolean char code input-output numeric random string])
|
||||||
(:use propeller.gp
|
(:use propeller.gp
|
||||||
propeller.push.instructions
|
propeller.push.instructions
|
||||||
[propeller.problems simple-regression string-classification]))
|
[propeller.problems simple-regression string-classification]))
|
||||||
@ -7,19 +8,18 @@
|
|||||||
(defn -main
|
(defn -main
|
||||||
"Runs propel-gp, giving it a map of arguments."
|
"Runs propel-gp, giving it a map of arguments."
|
||||||
[& args]
|
[& args]
|
||||||
(binding [*ns* (the-ns 'propeller.core)]
|
(gp (update-in (merge {:instructions default-instructions
|
||||||
(gp (update-in (merge {:instructions default-instructions
|
:error-function regression-error-function
|
||||||
:error-function regression-error-function
|
:max-generations 500
|
||||||
:max-generations 500
|
:population-size 500
|
||||||
:population-size 500
|
:max-initial-plushy-size 50
|
||||||
:max-initial-plushy-size 50
|
:step-limit 100
|
||||||
:step-limit 100
|
:parent-selection :lexicase
|
||||||
:parent-selection :lexicase
|
:tournament-size 5
|
||||||
:tournament-size 5
|
:umad-rate 0.1
|
||||||
:umad-rate 0.1
|
:variation {:umad 0.5 :crossover 0.5}
|
||||||
:variation {:umad 0.5 :crossover 0.5}
|
:elitism false}
|
||||||
:elitism false}
|
(apply hash-map
|
||||||
(apply hash-map
|
(map read-string args)))
|
||||||
(map read-string args)))
|
[:error-function]
|
||||||
[:error-function]
|
#(if (fn? %) % (eval %)))))
|
||||||
#(if (fn? %) % (eval %))))))
|
|
||||||
|
@ -1,16 +1,61 @@
|
|||||||
(ns propeller.push.instructions
|
(ns propeller.push.instructions
|
||||||
(:use propeller.push.state)
|
(:require [propeller.push.state :refer [get-args-from-stacks
|
||||||
(:require [tools.character :as char]))
|
push-to-stack]]))
|
||||||
|
|
||||||
;; =============================================================================
|
;; =============================================================================
|
||||||
;; PushGP Instructions
|
;; PushGP Instructions
|
||||||
;;
|
;;
|
||||||
|
;; Instructions are represented as keywords, and stored in an atom.
|
||||||
|
;;
|
||||||
;; Instructions must all be either functions that take one Push state and
|
;; Instructions must all be either functions that take one Push state and
|
||||||
;; return another, or constant literals.
|
;; return another, or constant literals.
|
||||||
;;
|
;;
|
||||||
;; TMH: ERCs?
|
;; TMH: ERCs?
|
||||||
;; =============================================================================
|
;; =============================================================================
|
||||||
|
|
||||||
|
;; Set of original propel instructions
|
||||||
|
(def default-instructions
|
||||||
|
(list :in1
|
||||||
|
:integer_+
|
||||||
|
:integer_-
|
||||||
|
:integer_*
|
||||||
|
:integer_%
|
||||||
|
:integer_=
|
||||||
|
:exec_dup
|
||||||
|
:exec_if
|
||||||
|
:boolean_and
|
||||||
|
:boolean_or
|
||||||
|
:boolean_not
|
||||||
|
:boolean_=
|
||||||
|
:string_=
|
||||||
|
:string_take
|
||||||
|
:string_drop
|
||||||
|
:string_reverse
|
||||||
|
:string_concat
|
||||||
|
:string_length
|
||||||
|
:string_includes?
|
||||||
|
'close
|
||||||
|
0
|
||||||
|
1
|
||||||
|
true
|
||||||
|
false
|
||||||
|
""
|
||||||
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
|
"A"
|
||||||
|
"C"
|
||||||
|
"G"
|
||||||
|
"T"))
|
||||||
|
|
||||||
|
(def instruction-table (atom (hash-map)))
|
||||||
|
|
||||||
|
(defmacro def-instruction
|
||||||
|
[instruction definition]
|
||||||
|
`(swap! instruction-table assoc '~instruction ~definition))
|
||||||
|
|
||||||
|
;; Number of blocks opened by instructions (default = 0)
|
||||||
|
(def opens {:exec_dup 1
|
||||||
|
:exec_if 2})
|
||||||
|
|
||||||
(defn make-instruction
|
(defn make-instruction
|
||||||
"A utility function for making Push instructions. Takes a state, a function
|
"A utility function for making Push instructions. Takes a state, a function
|
||||||
to apply to the args, the stacks to take the args from, and the stack to
|
to apply to the args, the stacks to take the args from, and the stack to
|
||||||
@ -23,272 +68,3 @@
|
|||||||
(let [result (apply function (:args popped-args))
|
(let [result (apply function (:args popped-args))
|
||||||
new-state (:state popped-args)]
|
new-state (:state popped-args)]
|
||||||
(push-to-stack new-state return-stack result)))))
|
(push-to-stack new-state return-stack result)))))
|
||||||
|
|
||||||
;; Original propel instructions
|
|
||||||
(def default-instructions
|
|
||||||
(list
|
|
||||||
'in1
|
|
||||||
'integer_+
|
|
||||||
'integer_-
|
|
||||||
'integer_*
|
|
||||||
'integer_%
|
|
||||||
'integer_=
|
|
||||||
'exec_dup
|
|
||||||
'exec_if
|
|
||||||
'boolean_and
|
|
||||||
'boolean_or
|
|
||||||
'boolean_not
|
|
||||||
'boolean_=
|
|
||||||
'string_=
|
|
||||||
'string_take
|
|
||||||
'string_drop
|
|
||||||
'string_reverse
|
|
||||||
'string_concat
|
|
||||||
'string_length
|
|
||||||
'string_includes?
|
|
||||||
'close
|
|
||||||
0
|
|
||||||
1
|
|
||||||
true
|
|
||||||
false
|
|
||||||
""
|
|
||||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
|
||||||
"A"
|
|
||||||
"C"
|
|
||||||
"G"
|
|
||||||
"T"))
|
|
||||||
|
|
||||||
;; Number of blocks opened by instructions (default = 0)
|
|
||||||
(def opens
|
|
||||||
{'exec_dup 1
|
|
||||||
'exec_if 2})
|
|
||||||
|
|
||||||
;; =============================================================================
|
|
||||||
;; BOOLEAN
|
|
||||||
;; =============================================================================
|
|
||||||
|
|
||||||
(defn boolean_=
|
|
||||||
"Pushes TRUE if the top two BOOLEANs are equal, and FALSE otherwise."
|
|
||||||
[state]
|
|
||||||
(make-instruction state = [:boolean :boolean] :boolean))
|
|
||||||
|
|
||||||
(defn boolean_and
|
|
||||||
[state]
|
|
||||||
"Pushes the logical AND of the top two BOOLEANs."
|
|
||||||
(make-instruction state #(and %1 %2) [:boolean :boolean] :boolean))
|
|
||||||
|
|
||||||
(defn boolean_or
|
|
||||||
[state]
|
|
||||||
"Pushes the logical OR of the top two BOOLEANs."
|
|
||||||
(make-instruction state #(or %1 %2) [:boolean :boolean] :boolean))
|
|
||||||
|
|
||||||
(defn boolean_not
|
|
||||||
[state]
|
|
||||||
"Pushes the logical NOT of the top BOOLEAN."
|
|
||||||
(make-instruction state not [:boolean] :boolean))
|
|
||||||
|
|
||||||
(defn boolean_xor
|
|
||||||
[state]
|
|
||||||
"Pushes the logical XOR of the top two BOOLEANs."
|
|
||||||
(make-instruction state #(or (and %1 (not %2))
|
|
||||||
(and (not %1) %2))
|
|
||||||
[:boolean :boolean]
|
|
||||||
:boolean))
|
|
||||||
|
|
||||||
(defn boolean_invert_first_then_and
|
|
||||||
[state]
|
|
||||||
"Pushes the logical AND of the top two BOOLEANs, after applying NOT to the
|
|
||||||
first one."
|
|
||||||
(make-instruction state #(and %1 (not %2)) [:boolean :boolean] :boolean))
|
|
||||||
|
|
||||||
(defn boolean_invert_second_then_and
|
|
||||||
[state]
|
|
||||||
"Pushes the logical AND of the top two BOOLEANs, after applying NOT to the
|
|
||||||
second one."
|
|
||||||
(make-instruction state #(and (not %1) %2) [:boolean :boolean] :boolean))
|
|
||||||
|
|
||||||
(defn boolean_fromfloat
|
|
||||||
[state]
|
|
||||||
"Pushes FALSE if the top FLOAT is 0.0, and TRUE otherwise."
|
|
||||||
(make-instruction state #(not (zero? %)) [:float] :boolean))
|
|
||||||
|
|
||||||
(defn boolean_frominteger
|
|
||||||
[state]
|
|
||||||
"Pushes FALSE if the top INTEGER is 0, and TRUE otherwise."
|
|
||||||
(make-instruction state #(not (zero? %)) [:integer] :boolean))
|
|
||||||
|
|
||||||
;; =============================================================================
|
|
||||||
;; CHAR
|
|
||||||
;; =============================================================================
|
|
||||||
|
|
||||||
(defn char_isletter
|
|
||||||
"Pushes TRUE onto the BOOLEAN stack if the popped character is a letter."
|
|
||||||
[state]
|
|
||||||
(make-instruction state char/is-letter [:char] :boolean))
|
|
||||||
|
|
||||||
(defn char_isdigit
|
|
||||||
"Pushes TRUE onto the BOOLEAN stack if the popped character is a digit."
|
|
||||||
[state]
|
|
||||||
(make-instruction state char/is-digit [:char] :boolean))
|
|
||||||
|
|
||||||
(defn char_iswhitespace
|
|
||||||
"Pushes TRUE onto the BOOLEAN stack if the popped character is whitespace
|
|
||||||
(newline, space, or tab)."
|
|
||||||
[state]
|
|
||||||
(make-instruction state char/is-whitespace [:char] :boolean))
|
|
||||||
|
|
||||||
(defn char_allfromstring
|
|
||||||
"Pops the STRING stack and pushes the top element's constituent characters
|
|
||||||
onto the CHAR stack, in order. For instance, \"hello\" will result in the
|
|
||||||
top of the CHAR stack being o l l e h."
|
|
||||||
[state]
|
|
||||||
(make-instruction state #(map char %) [:string] :char))
|
|
||||||
|
|
||||||
(defn char_frominteger
|
|
||||||
"Pops the INTEGER stack and pushes the top element's corresponding ASCII
|
|
||||||
value onto the CHAR stack. Integers larger than 128 will be reduced modulo
|
|
||||||
128. For instance, 248 will result in x being pushed."
|
|
||||||
[state]
|
|
||||||
(make-instruction state #(char (mod % 128)) [:integer] :char))
|
|
||||||
|
|
||||||
(defn char_fromfloat
|
|
||||||
"Pops the FLOAT stack, converts the top item to a whole number, and pushes
|
|
||||||
its corresponding ASCII value onto the CHAR stack. Whole numbers larger than
|
|
||||||
128 will be reduced modulo 128. For instance, 248.45 will result in x being
|
|
||||||
pushed."
|
|
||||||
[state]
|
|
||||||
(make-instruction state #(char (mod (long %) 128)) [:float] :char))
|
|
||||||
|
|
||||||
;; =============================================================================
|
|
||||||
;; CODE
|
|
||||||
;; =============================================================================
|
|
||||||
|
|
||||||
;; ...to be added
|
|
||||||
|
|
||||||
;; =============================================================================
|
|
||||||
;; EXEC
|
|
||||||
;; =============================================================================
|
|
||||||
|
|
||||||
(defn exec_dup
|
|
||||||
[state]
|
|
||||||
(if (empty-stack? state :exec)
|
|
||||||
state
|
|
||||||
(push-to-stack state :exec (first (:exec state)))))
|
|
||||||
|
|
||||||
(defn exec_if
|
|
||||||
[state]
|
|
||||||
(make-instruction state #(if %1 %3 %2) [:boolean :exec :exec] :exec))
|
|
||||||
|
|
||||||
;; =============================================================================
|
|
||||||
;; ENVIRONMENT
|
|
||||||
;; =============================================================================
|
|
||||||
|
|
||||||
;; ...to be added
|
|
||||||
|
|
||||||
;; =============================================================================
|
|
||||||
;; GENETIC TURING MACHINE
|
|
||||||
;; =============================================================================
|
|
||||||
|
|
||||||
;; ...to be added
|
|
||||||
|
|
||||||
;; =============================================================================
|
|
||||||
;; GENOME
|
|
||||||
;; =============================================================================
|
|
||||||
|
|
||||||
;; ...to be added
|
|
||||||
|
|
||||||
;; =============================================================================
|
|
||||||
;; INPUT-OUTPUT
|
|
||||||
;; =============================================================================
|
|
||||||
|
|
||||||
(defn in1
|
|
||||||
"Pushes the input labeled :in1 on the inputs map onto the :exec stack."
|
|
||||||
[state]
|
|
||||||
(push-to-stack state :exec (:in1 (:input state))))
|
|
||||||
|
|
||||||
;; =============================================================================
|
|
||||||
;; INTEGER AND FLOAT
|
|
||||||
;; =============================================================================
|
|
||||||
|
|
||||||
(defn integer_=
|
|
||||||
[state]
|
|
||||||
(make-instruction state = [:integer :integer] :boolean))
|
|
||||||
|
|
||||||
(defn integer_+
|
|
||||||
[state]
|
|
||||||
(make-instruction state +' [:integer :integer] :integer))
|
|
||||||
|
|
||||||
(defn integer_-
|
|
||||||
[state]
|
|
||||||
(make-instruction state -' [:integer :integer] :integer))
|
|
||||||
|
|
||||||
(defn integer_*
|
|
||||||
[state]
|
|
||||||
(make-instruction state *' [:integer :integer] :integer))
|
|
||||||
|
|
||||||
(defn integer_%
|
|
||||||
[state]
|
|
||||||
(make-instruction state
|
|
||||||
(fn [int1 int2]
|
|
||||||
(if (zero? int2) int1 (quot int1 int2)))
|
|
||||||
[:integer :integer]
|
|
||||||
:integer))
|
|
||||||
|
|
||||||
;; =============================================================================
|
|
||||||
;; RANDOM
|
|
||||||
;; =============================================================================
|
|
||||||
|
|
||||||
(defn boolean_rand
|
|
||||||
[state]
|
|
||||||
"Pushes a random BOOLEAN."
|
|
||||||
(make-instruction state #(rand-nth [true false]) [] :boolean))
|
|
||||||
|
|
||||||
;; =============================================================================
|
|
||||||
;; STRING
|
|
||||||
;; =============================================================================
|
|
||||||
|
|
||||||
(defn string_=
|
|
||||||
[state]
|
|
||||||
(make-instruction state = [:string :string] :boolean))
|
|
||||||
|
|
||||||
(defn string_concat
|
|
||||||
[state]
|
|
||||||
(make-instruction state #(apply str (concat %1 %2)) [:string :string] :string))
|
|
||||||
|
|
||||||
(defn string_drop
|
|
||||||
[state]
|
|
||||||
(make-instruction state #(apply str (drop %1 %2)) [:integer :string] :string))
|
|
||||||
|
|
||||||
(defn string_includes?
|
|
||||||
[state]
|
|
||||||
(make-instruction state clojure.string/includes? [:string :string] :boolean))
|
|
||||||
|
|
||||||
(defn string_length
|
|
||||||
[state]
|
|
||||||
(make-instruction state count [:string] :integer))
|
|
||||||
|
|
||||||
(defn string_reverse
|
|
||||||
[state]
|
|
||||||
(make-instruction state #(apply str (reverse %)) [:string] :string))
|
|
||||||
|
|
||||||
(defn string_take
|
|
||||||
[state]
|
|
||||||
(make-instruction state #(apply str (take %1 %2)) [:integer :string] :string))
|
|
||||||
|
|
||||||
;; =============================================================================
|
|
||||||
;; TAG
|
|
||||||
;; =============================================================================
|
|
||||||
|
|
||||||
;; ...to be added
|
|
||||||
|
|
||||||
;; =============================================================================
|
|
||||||
;; VECTOR
|
|
||||||
;; =============================================================================
|
|
||||||
|
|
||||||
;; ...to be added
|
|
||||||
|
|
||||||
;; =============================================================================
|
|
||||||
;; ZIP
|
|
||||||
;; =============================================================================
|
|
||||||
|
|
||||||
;; ...to be added
|
|
||||||
|
62
src/propeller/push/instructions/boolean.clj
Normal file
62
src/propeller/push/instructions/boolean.clj
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
(ns propeller.push.instructions.boolean
|
||||||
|
(:require [propeller.push.instructions :refer [make-instruction
|
||||||
|
def-instruction]]))
|
||||||
|
|
||||||
|
;; Pushes TRUE if the top two BOOLEANs are equal, and FALSE otherwise
|
||||||
|
(def-instruction
|
||||||
|
:boolean_=
|
||||||
|
(fn [state]
|
||||||
|
(make-instruction state = [:boolean :boolean] :boolean)))
|
||||||
|
|
||||||
|
;; Pushes the logical AND of the top two BOOLEANs
|
||||||
|
(def-instruction
|
||||||
|
:boolean_and
|
||||||
|
(fn [state]
|
||||||
|
(make-instruction state #(and %1 %2) [:boolean :boolean] :boolean)))
|
||||||
|
|
||||||
|
;; Pushes the logical OR of the top two BOOLEANs
|
||||||
|
(def-instruction
|
||||||
|
:boolean_or
|
||||||
|
(fn [state]
|
||||||
|
(make-instruction state #(or %1 %2) [:boolean :boolean] :boolean)))
|
||||||
|
|
||||||
|
;; Pushes the logical NOT of the top BOOLEAN
|
||||||
|
(def-instruction
|
||||||
|
:boolean_not
|
||||||
|
(fn [state]
|
||||||
|
(make-instruction state not [:boolean] :boolean)))
|
||||||
|
|
||||||
|
;; Pushes the logical XOR of the top two BOOLEAN
|
||||||
|
(def-instruction
|
||||||
|
:boolean_xor
|
||||||
|
(fn [state]
|
||||||
|
(make-instruction state #(or (and %1 (not %2))
|
||||||
|
(and (not %1) %2))
|
||||||
|
[:boolean :boolean]
|
||||||
|
:boolean)))
|
||||||
|
|
||||||
|
;; Pushes the logical AND of the top two BOOLEANs, after applying NOT to the
|
||||||
|
;; first one
|
||||||
|
(def-instruction
|
||||||
|
:boolean_invert_first_then_and
|
||||||
|
(fn [state]
|
||||||
|
(make-instruction state #(and %1 (not %2)) [:boolean :boolean] :boolean)))
|
||||||
|
|
||||||
|
;; Pushes the logical AND of the top two BOOLEANs, after applying NOT to the
|
||||||
|
;; second one
|
||||||
|
(def-instruction
|
||||||
|
:boolean_invert_second_then_and
|
||||||
|
(fn [state]
|
||||||
|
(make-instruction state #(and (not %1) %2) [:boolean :boolean] :boolean)))
|
||||||
|
|
||||||
|
;; Pushes FALSE if the top FLOAT is 0.0, and TRUE otherwise
|
||||||
|
(def-instruction
|
||||||
|
:boolean_fromfloat
|
||||||
|
(fn [state]
|
||||||
|
(make-instruction state #(not (zero? %)) [:float] :boolean)))
|
||||||
|
|
||||||
|
;; Pushes FALSE if the top INTEGER is 0, and TRUE otherwise
|
||||||
|
(def-instruction
|
||||||
|
:boolean_frominteger
|
||||||
|
(fn [state]
|
||||||
|
(make-instruction state #(not (zero? %)) [:integer] :boolean)))
|
48
src/propeller/push/instructions/char.clj
Normal file
48
src/propeller/push/instructions/char.clj
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
(ns propeller.push.instructions.char
|
||||||
|
(:require [propeller.push.instructions :refer [make-instruction
|
||||||
|
def-instruction]]
|
||||||
|
[tools.character :as char]))
|
||||||
|
|
||||||
|
;; Pushes TRUE onto the BOOLEAN stack if the popped character is a letter
|
||||||
|
(def-instruction
|
||||||
|
:char_isletter
|
||||||
|
(fn [state]
|
||||||
|
(make-instruction state char/is-letter [:char] :boolean)))
|
||||||
|
|
||||||
|
;; Pushes TRUE onto the BOOLEAN stack if the popped character is a digit
|
||||||
|
(def-instruction
|
||||||
|
:char_isdigit
|
||||||
|
(fn [state]
|
||||||
|
(make-instruction state char/is-digit [:char] :boolean)))
|
||||||
|
|
||||||
|
;; Pushes TRUE onto the BOOLEAN stack if the popped character is whitespace
|
||||||
|
;; (newline, space, or tab)
|
||||||
|
(def-instruction
|
||||||
|
:char_iswhitespace
|
||||||
|
(fn [state]
|
||||||
|
(make-instruction state char/is-whitespace [:char] :boolean)))
|
||||||
|
|
||||||
|
;; Pops the STRING stack and pushes the top element's constituent characters
|
||||||
|
;; onto the CHAR stack, in order. For instance, "hello" will result in the
|
||||||
|
;; top of the CHAR stack being o l l e h
|
||||||
|
(def-instruction
|
||||||
|
:char_allfromstring
|
||||||
|
(fn [state]
|
||||||
|
(make-instruction state #(map char %) [:string] :char)))
|
||||||
|
|
||||||
|
;; Pops the INTEGER stack and pushes the top element's corresponding ASCII
|
||||||
|
;; value onto the CHAR stack. Integers larger than 128 will be reduced modulo
|
||||||
|
;; 128. For instance, 248 will result in x being pushed
|
||||||
|
(def-instruction
|
||||||
|
:char_frominteger
|
||||||
|
(fn [state]
|
||||||
|
(make-instruction state #(char (mod % 128)) [:integer] :char)))
|
||||||
|
|
||||||
|
;; Pops the FLOAT stack, converts the top item to a whole number, and pushes
|
||||||
|
;; its corresponding ASCII value onto the CHAR stack. Whole numbers larger than
|
||||||
|
;; 128 will be reduced modulo 128. For instance, 248.45 will result in x being
|
||||||
|
;; pushed.
|
||||||
|
(def-instruction
|
||||||
|
:char_fromfloat
|
||||||
|
(fn [state]
|
||||||
|
(make-instruction state #(char (mod (long %) 128)) [:float] :char)))
|
16
src/propeller/push/instructions/code.clj
Normal file
16
src/propeller/push/instructions/code.clj
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
(ns propeller.push.instructions.code
|
||||||
|
(:require [propeller.push.state :as state]
|
||||||
|
[propeller.push.instructions :refer [make-instruction
|
||||||
|
def-instruction]]))
|
||||||
|
|
||||||
|
(def-instruction
|
||||||
|
:exec_dup
|
||||||
|
(fn [state]
|
||||||
|
(if (state/empty-stack? state :exec)
|
||||||
|
state
|
||||||
|
(state/push-to-stack state :exec (first (:exec state))))))
|
||||||
|
|
||||||
|
(def-instruction
|
||||||
|
:exec_if
|
||||||
|
(fn [state]
|
||||||
|
(make-instruction state #(if %1 %3 %2) [:boolean :exec :exec] :exec)))
|
9
src/propeller/push/instructions/input_output.clj
Normal file
9
src/propeller/push/instructions/input_output.clj
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
(ns propeller.push.instructions.input-output
|
||||||
|
(:require [propeller.push.state :as state]
|
||||||
|
[propeller.push.instructions :refer [def-instruction]]))
|
||||||
|
|
||||||
|
;; Pushes the input labeled :in1 on the inputs map onto the :exec stack
|
||||||
|
(def-instruction
|
||||||
|
:in1
|
||||||
|
(fn [state]
|
||||||
|
(state/push-to-stack state :exec (:in1 (:input state)))))
|
32
src/propeller/push/instructions/numeric.clj
Normal file
32
src/propeller/push/instructions/numeric.clj
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
(ns propeller.push.instructions.numeric
|
||||||
|
(:require [propeller.push.instructions :refer [make-instruction
|
||||||
|
def-instruction]]))
|
||||||
|
|
||||||
|
(def-instruction
|
||||||
|
:integer_=
|
||||||
|
(fn [state]
|
||||||
|
(make-instruction state = [:integer :integer] :boolean)))
|
||||||
|
|
||||||
|
(def-instruction
|
||||||
|
:integer_+
|
||||||
|
(fn [state]
|
||||||
|
(make-instruction state +' [:integer :integer] :integer)))
|
||||||
|
|
||||||
|
(def-instruction
|
||||||
|
:integer_-
|
||||||
|
(fn [state]
|
||||||
|
(make-instruction state -' [:integer :integer] :integer)))
|
||||||
|
|
||||||
|
(def-instruction
|
||||||
|
:integer_*
|
||||||
|
(fn [state]
|
||||||
|
(make-instruction state *' [:integer :integer] :integer)))
|
||||||
|
|
||||||
|
(def-instruction
|
||||||
|
:integer_%
|
||||||
|
(fn [state]
|
||||||
|
(make-instruction state
|
||||||
|
(fn [int1 int2]
|
||||||
|
(if (zero? int2) int1 (quot int1 int2)))
|
||||||
|
[:integer :integer]
|
||||||
|
:integer)))
|
9
src/propeller/push/instructions/random.clj
Normal file
9
src/propeller/push/instructions/random.clj
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
(ns propeller.push.instructions.random
|
||||||
|
(:require [propeller.push.instructions :refer [def-instruction
|
||||||
|
make-instruction]]))
|
||||||
|
|
||||||
|
;; Pushes a random BOOLEAN
|
||||||
|
(def-instruction
|
||||||
|
:boolean_rand
|
||||||
|
(fn [state]
|
||||||
|
(make-instruction state #(rand-nth [true false]) [] :boolean)))
|
38
src/propeller/push/instructions/string.clj
Normal file
38
src/propeller/push/instructions/string.clj
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
(ns propeller.push.instructions.string
|
||||||
|
(:require [propeller.push.instructions :refer [def-instruction
|
||||||
|
make-instruction]]))
|
||||||
|
|
||||||
|
(def-instruction
|
||||||
|
:string_=
|
||||||
|
(fn [state]
|
||||||
|
(make-instruction state = [:string :string] :boolean)))
|
||||||
|
|
||||||
|
(def-instruction
|
||||||
|
:string_concat
|
||||||
|
(fn [state]
|
||||||
|
(make-instruction state #(apply str (concat %1 %2)) [:string :string] :string)))
|
||||||
|
|
||||||
|
(def-instruction
|
||||||
|
:string_drop
|
||||||
|
(fn [state]
|
||||||
|
(make-instruction state #(apply str (drop %1 %2)) [:integer :string] :string)))
|
||||||
|
|
||||||
|
(def-instruction
|
||||||
|
:string_includes?
|
||||||
|
(fn [state]
|
||||||
|
(make-instruction state clojure.string/includes? [:string :string] :boolean)))
|
||||||
|
|
||||||
|
(def-instruction
|
||||||
|
:string_length
|
||||||
|
(fn [state]
|
||||||
|
(make-instruction state count [:string] :integer)))
|
||||||
|
|
||||||
|
(def-instruction
|
||||||
|
:string_reverse
|
||||||
|
(fn [state]
|
||||||
|
(make-instruction state #(apply str (reverse %)) [:string] :string)))
|
||||||
|
|
||||||
|
(def-instruction
|
||||||
|
:string_take
|
||||||
|
(fn [state]
|
||||||
|
(make-instruction state #(apply str (take %1 %2)) [:integer :string] :string)))
|
@ -1,14 +1,15 @@
|
|||||||
(ns propeller.push.interpreter
|
(ns propeller.push.interpreter
|
||||||
(:use [propeller.push state instructions]))
|
(:require [propeller.push.instructions :refer [instruction-table]])
|
||||||
|
(:require [propeller.push.state :refer :all]))
|
||||||
|
|
||||||
(defn interpret-one-step
|
(defn interpret-one-step
|
||||||
"Takes a Push state and executes the next instruction on the exec stack."
|
"Takes a Push state and executes the next instruction on the exec stack."
|
||||||
[state]
|
[state]
|
||||||
(let [popped-state (pop-stack state :exec)
|
(let [popped-state (pop-stack state :exec)
|
||||||
first-raw (first (:exec state))
|
first-instruction-raw (first (:exec state))
|
||||||
first-instruction (if (symbol? first-raw)
|
first-instruction (if (keyword? first-instruction-raw)
|
||||||
(var-get (resolve first-raw))
|
(first-instruction-raw @instruction-table)
|
||||||
first-raw)]
|
first-instruction-raw)]
|
||||||
(cond
|
(cond
|
||||||
(fn? first-instruction)
|
(fn? first-instruction)
|
||||||
(first-instruction popped-state)
|
(first-instruction popped-state)
|
||||||
@ -27,7 +28,7 @@
|
|||||||
;
|
;
|
||||||
:else
|
:else
|
||||||
(throw (Exception. (str "Unrecognized Push instruction in program: "
|
(throw (Exception. (str "Unrecognized Push instruction in program: "
|
||||||
first-instruction))))))
|
(name first-instruction-raw)))))))
|
||||||
|
|
||||||
(defn interpret-program
|
(defn interpret-program
|
||||||
"Runs the given problem starting with the stacks in start-state."
|
"Runs the given problem starting with the stacks in start-state."
|
||||||
|
1
src/propeller/push/utils.clj
Normal file
1
src/propeller/push/utils.clj
Normal file
@ -0,0 +1 @@
|
|||||||
|
(ns propeller.push.utils)
|
Loading…
x
Reference in New Issue
Block a user