#!/usr/local/bin/sbcl --script (defvar stack '()) (defvar memory '()) ;; Split str based on chr (defun split-string (chr str) (loop for i = 0 then (1+ j) as j = (position chr str :start i) collect (subseq str i j) while j)) (defun empty-string-p (str) "Checks if string is empty i.e. '' " (equal str "")) (defmacro length-1 (lst) `(1- (length ,lst))) (defmacro churro-length (ch) `(- (length-1 ,ch) 3)) (defmacro filled-p (ch dir) "Check if churro is filled or empty dir = :right or :left" (case dir (:left `(equal #\* (char ,ch 1))) (:right `(equal #\* (char ,ch (- (length ,ch) 2)))))) (defmacro get-dir (ch) `(if (or (equal #\* (char ,ch 1)) (equal #\o (char ,ch 1))) :left :right)) (defun get-churros (churros) "split source and filter out non-churros" (let ((split-list (remove-if #'empty-string-p (split-string #\Space churros))) (pure-list '())) (loop for chro in split-list do (when (equal #\{ (char chro 0)) (push chro pure-list))) (reverse pure-list))) (defun push-churro (churro) "Push a literal churro on the stack" ;;Set val to the number of "=" in churro (let ((val (churro-length churro))) ;; if churro is "filled" {*} add negative number, otherwise positive (cond ((filled-p churro :left) (push (- 0 val) stack)) (t (push val stack))) )) (defun store-churro (loc val) "Save a value to memory" (if (assoc loc memory) ;if there's a value already stored in slot (rplacd (assoc loc memory) val) ;replace it with the new one (push `(,loc . ,val) memory));else add loc and val to memmory ) (defmacro retreive-churro (loc) "retreive value at memory location" `(cdr (assoc ,loc memory))) (defun find-matches (ch-list) "Search from beginging for #3 and from the end for #4 to find indexes of matches" (cond ;list has no matching churros, return nil ((not (and (position "{o}===}" ch-list :test #'equal)(position "{o}====}" ch-list :test #'equal :from-end t))) nil) ; find #4 but not a #3 (t (format t "found Churros!")) );end cond ) (defun process-churros (ch-list) (loop for index from 0 to (length-1 ch-list) for churro = (nth index ch-list) for len = (churro-length churro) do (cond ;LITERAL churro: push on stack ((eq :left (get-dir churro)) (push-churro churro)) ;process FILLED churros {*} ((filled-p churro :right) (case len (0 (nth 0 stack)) ;pop and discard value (1 (push (+ (nth 1 stack)(nth 0 stack)) stack)) ;pop top 2 and add (2 (push (- (nth 1 stack)(nth 0 stack)) stack)) (5 (store-churro (nth 0 stack)(nth 1 stack))) (6 (push (retreive-churro (nth 0 stack)) stack)) (7 (format t "~d" (nth 0 stack))) (8 (format t "~a" (code-char (nth 0 stack)))) (9 (push (char-code (read-char)) stack)) (10 (return)) (3 ()) )) ;process EMPTY churros {o} ((not (filled-p churro :right)) (case len (0 (pop stack)) ;pop and discard value (1 (push (+ (pop stack)(pop stack)) stack)) ;pop top 2 and add (2 (push (let ((valA (pop stack)) (valB (pop stack)))(- valB valA)) stack)) (5 (store-churro (pop stack)(pop stack))) (6 (push (retreive-churro (pop stack)) stack)) (7 (format t "~d" (pop stack))) (8 (format t "~a" (code-char (pop stack)))) (9 (push (char-code (read-char)) stack)) (10 (return)) (3 ()) ) );end Empty Churros ;else Not a Churro (t (format t "NaC: ~a~%" churro)) ));cond/loop (format t "~% Memory: ~S~% Stack:~%~{~2t~d~%~}" memory stack) );defun