Skip to content

Instantly share code, notes, and snippets.



Last active Aug 29, 2015
What would you like to do?
Random Function Generator
;;; Robert Estelle 23 Aug 2014
(defun random-elt (&rest lists)
; Return random element from lists
(let ((combined (apply #'concatenate 'list lists)))
(elt combined (random (length combined)))))
(defun funwith (fn num-args vars ops max-op-depth)
; Generate a random operation with the given function `fn` which takes
; `num-args` arguments. The scalar variables `vars` may be used, or any of
; the `ops` wich are pairs of (name num-args). Will use ops recursively until
; `max-op-depth` is exhausted.
(let ((args (loop for i to (- num-args 1) collect
(if (> max-op-depth 1)
(destructuring-bind (op num-op-args) (random-elt ops)
(funwith op num-op-args vars ops (- max-op-depth 1)))
(random-elt vars)))))
`(,fn ,@args)))
(defun gensyms (num-syms)
; Generate multiple internal symbols
(loop for i to (- num-syms 1) collect (gensym)))
(defun generate-random-function (num-args ops complexity)
; Generates a random function, returning the variable list and the function
; body.
(let* ((vars (gensyms num-args))
(op-assoc (random-elt ops))
(op (car op-assoc))
(num-args (cadr op-assoc))
(body (funwith op num-args vars ops complexity)))
`(,vars ,body)))
(defmacro defrandom (fname num-args ops complexity)
; Defines a random function with the given name.
(let* ((fn (generate-random-function num-args ops complexity))
(vars (car fn))
(body (cdr fn)))
`(defun ,fname ,vars ,@body)))
; Define a function called "foo"
; Taking in two arguments
; Using the following base operations
; List of (operation, number of operands)
((+ 2) (- 2) (* 2) (/ 2) (expt 2) (exp 1) (sqrt 1))
; Nest operations three levels deep
(print #'foo)
;;; Outputs:
; (BLOCK FOO (* (SQRT (EXP #:G286087)) (+ (- #:G286087 #:G286086) (* #:G286086 #:G286086))))>
(print (foo 17 2))
;;; Outputs:
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment