;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; This file is part of "NOVA": NOVA = search + COCOMO tools ; Copyright, 2008, Tim Menzies tim@menzies.us ; ; NOVA is free software: you can redistribute it and/or modify ; it under the terms of the GNU General Public License as published by ; the Free Software Foundation, either version 3 of the License, or ; (at your option) any later version. ; ; NOVA is distributed in the hope that it will be useful, ; but WITHOUT ANY WARRANTY; without even the implied warranty of ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ; GNU General Public License for more details. ; You should have received a copy of the GNU General Public License ; a long with NOVA. If not, see . ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; guessing numbers (defun ?quantity (min max) "Returns a random number between min and max." (+ min (my-random (- max min)))) ;;; guessing list items (defun ?elt (l) "Returns a random item from a list." (elt l (floor (my-random (length l))))) (defun ?elts (l n) "Returns up to n random items from a list." (if (zerop n) nil (let ((any (?elt l))) (cons any (?elts (remove any l) (- n 1)))))) (defun ?any (l &key (control 0.8) (power 1)) "Returns any number of items from a list, favoring smaller selections." (let* ((factor (expt control power)) (r (?quantity 0 1)) (some (round (log r factor))) (enough (min (length l) (max 1 some)))) (?elts l enough))) (defun ?lots (l) "Returns lots of items from a list." (?any l :power 1)) (defun ?some (l) "Returns some items from a list." (?any l :power 2)) (defun ?few (l) "Returns a few items from a list." (?any l :power 3)) ;;; basic structs used in *db* (defstruct num min max) (defstruct bag range) (defmacro ?num (x) "Returns a number between min and max." `(?quantity (num-min ,x) (num-max ,x))) (defun ?bag (x) "Returns one item from range." (?elt (bag-range x))) ;;; *db* cache management (defun zap (key) "Removes key from the *db* cache." (setf (db-! *db*) (remove key (db-! *db*) :key #'car))) (defun zaps () "Removes all keys from the *db* cache." (setf (db-! *db*) nil)) ;;; guessing and caching values in *db* (defun ? (key) "Guess a value for a key in the *db* settings." (let ((range (geta key (db-settings *db*)))) (guess range))) (defun ! (key) "Retrieve from the cache, or guess and cache a value for a key." (let ((value (cdr (assoc key (db-! *db*))))) (unless value (setf value (? key)) (push (cons key value) (db-! *db*))) value)) (defun guess (range) "All guessable types must be registered here." (case (type-of range) (num (?num range)) (bag (?bag range)) (one-a (?one-a range)) (one-b (?one-b range)) (sf (?sf range)) (em (?em range)) (dr (?dr range)) (rm (?rm range)) (otherwise (warn "can't handle ~a of type ~a" range (type-of range))))) (defun guess-demo (&optional (*db* *db*)) "Demonstrates guessing and caching." (zaps) (format t "~a ~a~%" (! 'a) (! 'a)) (zaps) (format t "~a ~a~%" (! 'a) (! 'a)) t) (let ((db (make-db :settings `((a . ,(make-num :min 20 :max 40)) (b . ,(make-bag :range '(1 3 5 7 9))))))) (egs :guess (eg '(?quantity 10 20) :of "guessing a random number using ?quantity") (eg '(?num (make-num :min 10 :max 20)) :of "guessing a random number a num struct") (eg '(?elt '(a b c d e)) :of "guessing a random list item using ?elt") (eg '(?bag (make-bag :range '(1 2 3 4))) :of "guessing a random list item using a bag struct") (eg `(guess-demo ,db) :of "demonstrating guessing and caching")))