markov-algorithm.lisp 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. ;;;; markov-algorithm.lisp
  2. (defpackage #:markov-algorithm
  3. (:use #:cl)
  4. (:export #:make-formula
  5. #:lhs
  6. #:rhs
  7. #:formulap
  8. #:compile-markov-algorithm
  9. #:formulap
  10. #:schemep))
  11. (in-package #:markov-algorithm)
  12. (defun make-formula (lhs rhs finalp)
  13. (list lhs
  14. (if finalp
  15. :->.
  16. :->)
  17. rhs))
  18. (defun formulap (obj)
  19. (and (listp obj)
  20. (stringp (first obj))
  21. (member (second obj) '(:-> :->.))
  22. (stringp (third obj))))
  23. (defun lhs (formula)
  24. (first formula))
  25. (defun rhs (formula)
  26. (third formula))
  27. (defun finalp (formula)
  28. (eql (second formula) :->.))
  29. (defun schemep (obj)
  30. (and (listp obj)
  31. (every #'formulap obj)))
  32. (defun matching-formula (word scheme)
  33. (find-if (lambda (formula)
  34. (search (lhs formula) word))
  35. scheme))
  36. (defun split-word (word formula)
  37. (let ((len (length (lhs formula)))
  38. (pos (search (lhs formula) word)))
  39. (values (subseq word 0 pos)
  40. (subseq word pos (+ pos len))
  41. (subseq word (+ pos len)))))
  42. (defun word-substitution (word formula)
  43. (multiple-value-bind (prefix stem suffix) (split-word word formula)
  44. (declare (ignore stem))
  45. (concatenate 'string prefix (rhs formula) suffix)))
  46. #|
  47. First value: the next iteration or the same word if no formula matches.
  48. Second value: true if there are no more iterations, nil otherwise.
  49. Third value: true if no formula matches, nil otherwise.
  50. |#
  51. (defun next-word (word scheme)
  52. (let ((formula (matching-formula word scheme)))
  53. (cond ((null formula) (values word t t))
  54. ((finalp formula) (values (word-substitution word formula) t nil))
  55. (t (values (word-substitution word formula) nil nil)))))
  56. (defun compile-markov-algorithm (scheme &optional (max-iterations 100))
  57. "Given a Markov scheme, return a function applying it to strings and
  58. performing at most MAX-ITERATIONS. The function returns either the
  59. resulting string or NIL if the iteration limit has been reached."
  60. (check-type scheme (satisfies schemep))
  61. (check-type max-iterations (integer 0 *))
  62. (lambda (word)
  63. (check-type word string)
  64. (loop repeat max-iterations
  65. with end? = nil
  66. do (setf (values word end?) (next-word word scheme))
  67. when end? do (return word)
  68. finally (return nil))))